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");
128 if (opt_trace_pid
!= 0) {
129 if (opt_create_trace
) {
130 DBG("Create a userspace trace for pid %d", opt_trace_pid
);
131 ret
= lttng_ust_create_trace(opt_trace_pid
);
135 MSG("Trace created successfully!\nUse --start to start tracing.");
138 if (opt_start_trace
) {
139 DBG("Start trace for pid %d", opt_trace_pid
);
140 ret
= lttng_ust_start_trace(opt_trace_pid
);
144 MSG("Trace started successfully!");
145 } else if (opt_stop_trace
) {
146 DBG("Stop trace for pid %d", opt_trace_pid
);
147 ret
= lttng_ust_stop_trace(opt_trace_pid
);
151 MSG("Trace stopped successfully!");
159 ERR("%s", lttng_get_readable_code(ret
));
160 error
: /* fall through */
165 * set_opt_session_info
167 * Setup session_name, current_uuid, short_str_uuid and
168 * long_str_uuid using the command line options.
170 static void set_opt_session_info(void)
172 int count
, i
, short_len
;
174 struct lttng_session
*sessions
;
176 if (opt_session_uuid
!= NULL
) {
177 short_len
= sizeof(short_str_uuid
) - 1;
179 tok
= strchr(opt_session_uuid
, '.');
180 if (strlen(tok
+ 1) == short_len
) {
181 memcpy(short_str_uuid
, tok
+ 1, short_len
);
182 short_str_uuid
[short_len
] = '\0';
185 /* Get long real uuid_t from session daemon */
186 count
= lttng_list_sessions(&sessions
);
187 for (i
= 0; i
< count
; i
++) {
188 uuid_unparse(sessions
[i
].uuid
, long_str_uuid
);
189 if (strncmp(long_str_uuid
, short_str_uuid
, 8) == 0) {
190 uuid_copy(current_uuid
, sessions
[i
].uuid
);
196 if (opt_session_name
!= NULL
) {
197 session_name
= strndup(opt_session_name
, NAME_MAX
);
204 * Small function to shorten the 37 bytes long uuid_t
205 * string representation to 8 characters.
207 static void shorten_uuid(char *long_u
, char *short_u
)
209 memcpy(short_u
, long_u
, 8);
210 short_u
[UUID_SHORT_STR_LEN
- 1] = '\0';
216 * Set current session uuid to the current flow of
217 * command(s) using the already shorten uuid or
220 static int set_session_uuid(void)
224 struct lttng_session
*sessions
;
226 if (!uuid_is_null(current_uuid
)) {
227 lttng_set_current_session_uuid(¤t_uuid
);
231 count
= lttng_list_sessions(&sessions
);
237 for (i
= 0; i
< count
; i
++) {
238 uuid_unparse(sessions
[i
].uuid
, str_uuid
);
239 if (strncmp(str_uuid
, short_str_uuid
, 8) == 0) {
240 lttng_set_current_session_uuid(&sessions
[i
].uuid
);
255 * process_opt_list_traces
257 * Get list of all traces for a specific session uuid.
259 static int process_opt_list_traces(void)
262 struct lttng_trace
*traces
;
264 ret
= lttng_list_traces(¤t_uuid
, &traces
);
269 MSG("Userspace traces:");
270 for (i
= 0; i
< ret
; i
++) {
271 if (traces
[i
].type
== USERSPACE
) {
272 MSG("\t%d) %s (pid: %d): %s",
273 i
, traces
[i
].name
, traces
[i
].pid
,
274 get_cmdline_by_pid(traces
[i
].pid
));
280 MSG("Kernel traces:");
281 for (;i
< ret
; i
++) {
282 if (traces
[i
].type
== KERNEL
) {
283 MSG("\t%d) %s", i
, traces
[i
].name
);
294 * process_opt_create_session
296 * Create a new session using the name pass
297 * to the command line.
299 static int process_opt_create_session(void)
308 /* Auto session creation */
309 if (opt_create_session
== 0) {
311 timeinfo
= localtime(&rawtime
);
312 strftime(name
, sizeof(name
), "%Y%m%d-%H%M%S", timeinfo
);
313 session_name
= strndup(name
, sizeof(name
));
316 ret
= lttng_create_session(session_name
, &session_id
);
321 uuid_unparse(session_id
, str_uuid
);
322 uuid_copy(current_uuid
, session_id
);
323 shorten_uuid(str_uuid
, short_str_uuid
);
325 MSG("Session UUID created: %s.%s", session_name
, short_str_uuid
);
332 * process_opt_list_sessions
334 * Get the list of available sessions from
335 * the session daemon and print it to user.
337 static int process_opt_list_sessions(void)
340 char tmp_short_uuid
[9];
342 struct lttng_session
*sess
;
344 count
= lttng_list_sessions(&sess
);
345 DBG("Session count %d", count
);
351 MSG("Available sessions (UUIDs):");
352 for (i
= 0; i
< count
; i
++) {
353 uuid_unparse(sess
[i
].uuid
, str_uuid
);
354 shorten_uuid(str_uuid
, tmp_short_uuid
);
355 MSG(" %d) %s.%s", i
+1, sess
[i
].name
, tmp_short_uuid
);
359 MSG("\nTo select a session, use -s, --session UUID.");
368 * process_opt_list_apps
370 * Get the UST traceable pid list and print
373 static int process_opt_list_apps(void)
379 count
= lttng_ust_list_apps(&pids
);
385 MSG("LTTng UST traceable application [name (pid)]:");
386 for (i
=0; i
< count
; i
++) {
387 cmdline
= get_cmdline_by_pid(pids
[i
]);
388 if (cmdline
== NULL
) {
389 MSG("\t(not running) (%d)", pids
[i
]);
392 MSG("\t%s (%d)", cmdline
, pids
[i
]);
396 /* Allocated by lttng_ust_list_apps() */
408 * Get command line from /proc for a specific pid.
410 * On success, return an allocated string pointer pointing to
412 * On error, return NULL.
414 static char *get_cmdline_by_pid(pid_t pid
)
418 char *cmdline
= NULL
;
419 char path
[24]; /* Can't go bigger than /proc/65535/cmdline */
421 snprintf(path
, sizeof(path
), "/proc/%d/cmdline", pid
);
422 fp
= fopen(path
, "r");
427 /* Caller must free() *cmdline */
428 cmdline
= malloc(PATH_MAX
);
429 ret
= fread(cmdline
, 1, PATH_MAX
, fp
);
439 * Make sure that all options passed to the command line
440 * are compatible with each others.
442 * On error, return -1
443 * On success, return 0
445 static int validate_options(void)
447 /* Conflicting command */
448 if (opt_start_trace
&& opt_stop_trace
) {
449 ERR("Can't use --start and --stop together.");
451 /* If no PID specified and trace_kernel is off */
452 } else if ((opt_trace_pid
== 0 && opt_trace_kernel
== 0) &&
453 (opt_create_trace
|| opt_start_trace
|| opt_stop_trace
)) {
454 ERR("Please specify a PID using -p, --pid PID.");
456 } else if (opt_session_uuid
&& opt_create_session
) {
457 ERR("Please don't use -s and -c together. Useless action.");
459 } else if (opt_list_traces
&& opt_session_uuid
== NULL
) {
460 ERR("Can't use -t without -s, --session option.");
473 * Spawn a session daemon by forking and execv.
475 static int spawn_sessiond(char *pathname
)
480 MSG("Spawning session daemon");
484 * Spawn session daemon and tell
485 * it to signal us when ready.
487 execlp(pathname
, "ltt-sessiond", "--sig-parent", "--quiet", NULL
);
488 /* execlp only returns if error happened */
489 if (errno
== ENOENT
) {
490 ERR("No session daemon found. Use --sessiond-path.");
494 kill(getppid(), SIGTERM
); /* unpause parent */
496 } else if (pid
> 0) {
497 /* Wait for ltt-sessiond to start */
513 * Check if the session daemon is available using
514 * the liblttngctl API for the check. If not, try to
517 static int check_ltt_sessiond(void)
520 char *pathname
= NULL
, *alloc_pathname
= NULL
;
522 ret
= lttng_check_session_daemon();
524 /* Try command line option path */
525 if (opt_sessiond_path
!= NULL
) {
526 ret
= access(opt_sessiond_path
, F_OK
| X_OK
);
528 ERR("No such file: %s", opt_sessiond_path
);
531 pathname
= opt_sessiond_path
;
533 /* Try LTTNG_SESSIOND_PATH env variable */
534 pathname
= getenv(LTTNG_SESSIOND_PATH_ENV
);
537 /* Let's rock and roll */
538 if (pathname
== NULL
) {
539 ret
= asprintf(&alloc_pathname
, "ltt-sessiond");
543 pathname
= alloc_pathname
;
546 ret
= spawn_sessiond(pathname
);
547 free(alloc_pathname
);
549 ERR("Problem occurs when starting %s", pathname
);
561 * Setup signal handler for SIGCHLD and SIGTERM.
563 static int set_signal_handler(void)
569 if ((ret
= sigemptyset(&sigset
)) < 0) {
570 perror("sigemptyset");
574 sa
.sa_handler
= sighandler
;
577 if ((ret
= sigaction(SIGCHLD
, &sa
, NULL
)) < 0) {
582 if ((ret
= sigaction(SIGTERM
, &sa
, NULL
)) < 0) {
594 * Signal handler for the daemon
596 static void sighandler(int sig
)
600 DBG("SIGTERM catched");
601 clean_exit(EXIT_FAILURE
);
605 DBG("SIGCHLD catched");
608 DBG("Unknown signal %d catched", sig
);
618 void clean_exit(int code
)
631 int main(int argc
, char *argv
[])
635 progname
= argv
[0] ? argv
[0] : "lttng";
637 /* For Mathieu Desnoyers aka Dr Tracing */
638 if (strncmp(progname
, "drtrace", 7) == 0) {
639 MSG("%c[%d;%dmWelcome back Dr Tracing!%c[%dm\n\n", 27,1,33,27,0);
642 ret
= parse_args(argc
, (const char **) argv
);
644 clean_exit(EXIT_FAILURE
);
647 ret
= validate_options();
652 ret
= set_signal_handler();
657 if (opt_tracing_group
!= NULL
) {
658 DBG("Set tracing group to '%s'", opt_tracing_group
);
659 lttng_set_tracing_group(opt_tracing_group
);
662 /* If ask for kernel tracing, need root perms */
663 if (opt_trace_kernel
) {
664 DBG("Kernel tracing activated");
666 ERR("%s must be setuid root", progname
);
671 /* Check if the lttng session daemon is running.
672 * If no, a daemon will be spawned.
674 if (opt_no_sessiond
== 0 && (check_ltt_sessiond() < 0)) {
675 clean_exit(EXIT_FAILURE
);
678 ret
= process_client_opt();
This page took 0.042876 seconds and 5 git commands to generate.