2 * Copyright (c) 2011 David Goulet <david.goulet@polymtl.ca>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <sys/types.h>
33 #include <lttng/lttng.h>
39 static char *progname
;
40 static char *session_name
;
41 static char short_str_uuid
[UUID_SHORT_STR_LEN
];
42 static char long_str_uuid
[UUID_STR_LEN
];
43 static uuid_t current_uuid
;
46 static int process_client_opt(void);
47 static int process_opt_list_apps(void);
48 static int process_opt_list_sessions(void);
49 static int process_opt_list_traces(void);
50 static int process_opt_create_session(void);
51 static int set_session_uuid(void);
52 static void sighandler(int sig
);
53 static int set_signal_handler(void);
54 static int validate_options(void);
55 static char *get_cmdline_by_pid(pid_t pid
);
56 static void set_opt_session_info(void);
57 static void shorten_uuid(char *long_u
, char *short_u
);
62 * Process client request from the command line
63 * options. Every tracing action is done by the
66 static int process_client_opt(void)
70 set_opt_session_info();
73 ret
= process_opt_list_apps();
79 if (opt_list_session
) {
80 ret
= process_opt_list_sessions();
86 if (opt_destroy_session
) {
87 ret
= lttng_destroy_session(¤t_uuid
);
91 MSG("Session %s destroyed.", opt_session_uuid
);
94 if (!opt_list_session
&& !opt_list_apps
) {
95 if (uuid_is_null(current_uuid
)) {
96 /* If no session uuid, create session */
97 DBG("No session specified. Creating session.");
98 ret
= process_opt_create_session();
104 DBG("Set session uuid to %s", long_str_uuid
);
105 ret
= set_session_uuid();
107 ERR("Session UUID %s not found", opt_session_uuid
);
112 if (opt_list_traces
) {
113 ret
= process_opt_list_traces();
120 * Action on traces (kernel or/and userspace).
122 if (opt_trace_kernel
) {
123 ERR("Not implemented yet");
127 if (opt_trace_pid
!= 0) {
128 if (opt_create_trace
) {
129 DBG("Create a userspace trace for pid %d", opt_trace_pid
);
130 ret
= lttng_ust_create_trace(opt_trace_pid
);
134 MSG("Trace created successfully!\nUse --start to start tracing.");
137 if (opt_start_trace
) {
138 DBG("Start trace for pid %d", opt_trace_pid
);
139 ret
= lttng_ust_start_trace(opt_trace_pid
);
143 MSG("Trace started successfully!");
144 } else if (opt_stop_trace
) {
145 DBG("Stop trace for pid %d", opt_trace_pid
);
146 ret
= lttng_ust_stop_trace(opt_trace_pid
);
150 MSG("Trace stopped successfully!");
158 ERR("%s", lttng_get_readable_code(ret
));
166 * set_opt_session_info
168 * Setup session_name, current_uuid, short_str_uuid and
169 * long_str_uuid using the command line options.
171 static void set_opt_session_info(void)
173 int count
, i
, short_len
;
175 struct lttng_session
*sessions
;
177 if (opt_session_uuid
!= NULL
) {
178 short_len
= sizeof(short_str_uuid
) - 1;
180 tok
= strchr(opt_session_uuid
, '.');
181 if (strlen(tok
+ 1) == short_len
) {
182 memcpy(short_str_uuid
, tok
+ 1, short_len
);
183 short_str_uuid
[short_len
] = '\0';
186 /* Get long real uuid_t from session daemon */
187 count
= lttng_list_sessions(&sessions
);
188 for (i
= 0; i
< count
; i
++) {
189 uuid_unparse(sessions
[i
].uuid
, long_str_uuid
);
190 if (strncmp(long_str_uuid
, short_str_uuid
, 8) == 0) {
191 uuid_copy(current_uuid
, sessions
[i
].uuid
);
197 if (opt_session_name
!= NULL
) {
198 session_name
= strndup(opt_session_name
, NAME_MAX
);
205 * Small function to shorten the 37 bytes long uuid_t
206 * string representation to 8 characters.
208 static void shorten_uuid(char *long_u
, char *short_u
)
210 memcpy(short_u
, long_u
, 8);
211 short_u
[UUID_SHORT_STR_LEN
- 1] = '\0';
217 * Set current session uuid to the current flow of
218 * command(s) using the already shorten uuid or
221 static int set_session_uuid(void)
225 struct lttng_session
*sessions
;
227 if (!uuid_is_null(current_uuid
)) {
228 lttng_set_current_session_uuid(¤t_uuid
);
232 count
= lttng_list_sessions(&sessions
);
238 for (i
= 0; i
< count
; i
++) {
239 uuid_unparse(sessions
[i
].uuid
, str_uuid
);
240 if (strncmp(str_uuid
, short_str_uuid
, 8) == 0) {
241 lttng_set_current_session_uuid(&sessions
[i
].uuid
);
256 * process_opt_list_traces
258 * Get list of all traces for a specific session uuid.
260 static int process_opt_list_traces(void)
263 struct lttng_trace
*traces
;
265 ret
= lttng_list_traces(¤t_uuid
, &traces
);
270 MSG("Userspace traces:");
271 for (i
= 0; i
< ret
; i
++) {
272 if (traces
[i
].type
== USERSPACE
) {
273 MSG("\t%d) %s (pid: %d): %s",
274 i
, traces
[i
].name
, traces
[i
].pid
,
275 get_cmdline_by_pid(traces
[i
].pid
));
281 MSG("Kernel traces:");
282 for (;i
< ret
; i
++) {
283 if (traces
[i
].type
== KERNEL
) {
284 MSG("\t%d) %s", i
, traces
[i
].name
);
295 * process_opt_create_session
297 * Create a new session using the name pass
298 * to the command line.
300 static int process_opt_create_session(void)
309 /* Auto session creation */
310 if (opt_create_session
== 0) {
312 timeinfo
= localtime(&rawtime
);
313 strftime(name
, sizeof(name
), "%Y%m%d-%H%M%S", timeinfo
);
314 session_name
= strndup(name
, sizeof(name
));
317 ret
= lttng_create_session(session_name
, &session_id
);
322 uuid_unparse(session_id
, str_uuid
);
323 uuid_copy(current_uuid
, session_id
);
324 shorten_uuid(str_uuid
, short_str_uuid
);
326 MSG("Session UUID created: %s.%s", session_name
, short_str_uuid
);
333 * process_opt_list_sessions
335 * Get the list of available sessions from
336 * the session daemon and print it to user.
338 static int process_opt_list_sessions(void)
341 char tmp_short_uuid
[9];
343 struct lttng_session
*sess
;
345 count
= lttng_list_sessions(&sess
);
346 DBG("Session count %d", count
);
352 MSG("Available sessions (UUIDs):");
353 for (i
= 0; i
< count
; i
++) {
354 uuid_unparse(sess
[i
].uuid
, str_uuid
);
355 shorten_uuid(str_uuid
, tmp_short_uuid
);
356 MSG(" %d) %s.%s", i
+1, sess
[i
].name
, tmp_short_uuid
);
360 MSG("\nTo select a session, use -s, --session UUID.");
369 * process_opt_list_apps
371 * Get the UST traceable pid list and print
374 static int process_opt_list_apps(void)
380 count
= lttng_ust_list_apps(&pids
);
386 MSG("LTTng UST traceable application [name (pid)]:");
387 for (i
=0; i
< count
; i
++) {
388 cmdline
= get_cmdline_by_pid(pids
[i
]);
389 if (cmdline
== NULL
) {
390 MSG("\t(not running) (%d)", pids
[i
]);
393 MSG("\t%s (%d)", cmdline
, pids
[i
]);
397 /* Allocated by lttng_ust_list_apps() */
409 * Get command line from /proc for a specific pid.
411 * On success, return an allocated string pointer pointing to
413 * On error, return NULL.
415 static char *get_cmdline_by_pid(pid_t pid
)
419 char *cmdline
= NULL
;
420 char path
[24]; /* Can't go bigger than /proc/65535/cmdline */
422 snprintf(path
, sizeof(path
), "/proc/%d/cmdline", pid
);
423 fp
= fopen(path
, "r");
428 /* Caller must free() *cmdline */
429 cmdline
= malloc(PATH_MAX
);
430 ret
= fread(cmdline
, 1, PATH_MAX
, fp
);
440 * Make sure that all options passed to the command line
441 * are compatible with each others.
443 * On error, return -1
444 * On success, return 0
446 static int validate_options(void)
448 /* Conflicting command */
449 if (opt_start_trace
&& opt_stop_trace
) {
450 ERR("Can't use --start and --stop together.");
452 /* If no PID specified and trace_kernel is off */
453 } else if ((opt_trace_pid
== 0 && opt_trace_kernel
== 0) &&
454 (opt_create_trace
|| opt_start_trace
|| opt_stop_trace
)) {
455 ERR("Please specify a PID using -p, --pid PID.");
457 } else if (opt_session_uuid
&& opt_create_session
) {
458 ERR("Please don't use -s and -c together. Useless action.");
460 } else if (opt_list_traces
&& opt_session_uuid
== NULL
) {
461 ERR("Can't use -t without -s, --session option.");
474 * Spawn a session daemon by forking and execv.
476 static int spawn_sessiond(char *pathname
)
481 MSG("Spawning session daemon");
484 /* Spawn session daemon and tell
485 * it to signal us when ready.
487 ret
= execlp(pathname
, "ltt-sessiond", "--sig-parent", "--quiet", NULL
);
489 if (errno
== ENOENT
) {
490 ERR("No session daemon found. Use --sessiond-path.");
494 kill(getppid(), SIGTERM
);
498 } else if (pid
> 0) {
499 /* Wait for ltt-sessiond to start */
515 * Check if the session daemon is available using
516 * the liblttngctl API for the check. If not, try to
519 static int check_ltt_sessiond(void)
522 char *pathname
= NULL
;
524 ret
= lttng_check_session_daemon();
526 /* Try command line option path */
527 if (opt_sessiond_path
!= NULL
) {
528 ret
= access(opt_sessiond_path
, F_OK
| X_OK
);
530 ERR("No such file: %s", opt_sessiond_path
);
533 pathname
= opt_sessiond_path
;
535 /* Try LTTNG_SESSIOND_PATH env variable */
536 pathname
= getenv(LTTNG_SESSIOND_PATH_ENV
);
537 if (pathname
!= NULL
) {
538 /* strdup here in order to make the free()
541 pathname
= strdup(pathname
);
545 /* Let's rock and roll */
546 if (pathname
== NULL
) {
547 ret
= asprintf(&pathname
, "ltt-sessiond");
553 ret
= spawn_sessiond(pathname
);
556 ERR("Problem occurs when starting %s", pathname
);
568 * Setup signal handler for SIGCHLD and SIGTERM.
570 static int set_signal_handler(void)
576 if ((ret
= sigemptyset(&sigset
)) < 0) {
577 perror("sigemptyset");
581 sa
.sa_handler
= sighandler
;
584 if ((ret
= sigaction(SIGCHLD
, &sa
, NULL
)) < 0) {
589 if ((ret
= sigaction(SIGTERM
, &sa
, NULL
)) < 0) {
601 * Signal handler for the daemon
603 static void sighandler(int sig
)
607 DBG("SIGTERM catched");
608 clean_exit(EXIT_FAILURE
);
612 DBG("SIGCHLD catched");
615 DBG("Unknown signal %d catched", sig
);
625 void clean_exit(int code
)
638 int main(int argc
, char *argv
[])
642 progname
= argv
[0] ? argv
[0] : "lttng";
644 /* For Mathieu Desnoyers aka Dr Tracing */
645 if (strncmp(progname
, "drtrace", 7) == 0) {
646 MSG("%c[%d;%dmWelcome back Dr Tracing!%c[%dm\n\n", 27,1,33,27,0);
649 ret
= parse_args(argc
, (const char **) argv
);
651 clean_exit(EXIT_FAILURE
);
654 ret
= validate_options();
659 ret
= set_signal_handler();
664 if (opt_tracing_group
!= NULL
) {
665 DBG("Set tracing group to '%s'", opt_tracing_group
);
666 lttng_set_tracing_group(opt_tracing_group
);
669 /* If ask for kernel tracing, need root perms */
670 if (opt_trace_kernel
) {
671 DBG("Kernel tracing activated");
673 ERR("%s must be setuid root", progname
);
678 /* Check if the lttng session daemon is running.
679 * If no, a daemon will be spawned.
681 if (opt_no_sessiond
== 0 && (check_ltt_sessiond() < 0)) {
682 clean_exit(EXIT_FAILURE
);
685 ret
= process_client_opt();
This page took 0.044967 seconds and 5 git commands to generate.