X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=lttng%2Flttng.c;h=4c74d21fefb665172f2fac166e9de0b5ffee20c8;hp=c7ff4edde334dd5131e1b207c902498cc8fc5ce1;hb=96243366860d20e371efed0500070cdbc4a01ec7;hpb=e8f07c636c9943a0e2a48113bb8135a6c4f5ebd7 diff --git a/lttng/lttng.c b/lttng/lttng.c index c7ff4edde..4c74d21fe 100644 --- a/lttng/lttng.c +++ b/lttng/lttng.c @@ -30,20 +30,31 @@ #include #include -#include +#include #include "lttng.h" #include "lttngerr.h" /* Variables */ static char *progname; +static char *session_name; +static char short_str_uuid[UUID_SHORT_STR_LEN]; +static char long_str_uuid[UUID_STR_LEN]; +static uuid_t current_uuid; /* Prototypes */ static int process_client_opt(void); static int process_opt_list_apps(void); static int process_opt_list_sessions(void); +static int process_opt_list_traces(void); +static int process_opt_create_session(void); +static int set_session_uuid(void); static void sighandler(int sig); static int set_signal_handler(void); +static int validate_options(void); +static char *get_cmdline_by_pid(pid_t pid); +static void set_opt_session_info(void); +static void shorten_uuid(char *long_u, char *short_u); /* * start_client @@ -56,11 +67,7 @@ static int process_client_opt(void) { int ret; - /* Connect to the session daemon */ - ret = lttng_connect_sessiond(); - if (ret < 0) { - goto end; - } + set_opt_session_info(); if (opt_list_apps) { ret = process_opt_list_apps(); @@ -76,11 +83,250 @@ static int process_client_opt(void) } } + if (opt_destroy_session) { + ret = lttng_destroy_session(¤t_uuid); + if (ret < 0) { + goto end; + } + MSG("Session %s destroyed.", opt_session_uuid); + } + + if (!opt_list_session && !opt_list_apps) { + if (uuid_is_null(current_uuid)) { + /* If no session uuid, create session */ + DBG("No session specified. Creating session."); + ret = process_opt_create_session(); + if (ret < 0) { + goto end; + } + } + + DBG("Set session uuid to %s", long_str_uuid); + ret = set_session_uuid(); + if (ret < 0) { + ERR("Session UUID %s not found", opt_session_uuid); + goto error; + } + } + + if (opt_list_traces) { + ret = process_opt_list_traces(); + if (ret < 0) { + goto end; + } + } + + /* + * Action on traces (kernel or/and userspace). + */ + if (opt_trace_kernel) { + ERR("Not implemented yet"); + goto end; + } + + if (opt_trace_pid != 0) { + if (opt_create_trace) { + DBG("Create a userspace trace for pid %d", opt_trace_pid); + ret = lttng_ust_create_trace(opt_trace_pid); + if (ret < 0) { + goto end; + } + MSG("Trace created successfully!\nUse --start to start tracing."); + } + + if (opt_start_trace) { + DBG("Start trace for pid %d", opt_trace_pid); + ret = lttng_ust_start_trace(opt_trace_pid); + if (ret < 0) { + goto end; + } + MSG("Trace started successfully!"); + } else if (opt_stop_trace) { + DBG("Stop trace for pid %d", opt_trace_pid); + ret = lttng_ust_stop_trace(opt_trace_pid); + if (ret < 0) { + goto end; + } + MSG("Trace stopped successfully!"); + } + + } + return 0; end: ERR("%s", lttng_get_readable_code(ret)); return ret; + +error: + return ret; +} + +/* + * set_opt_session_info + * + * Setup session_name, current_uuid, short_str_uuid and + * long_str_uuid using the command line options. + */ +static void set_opt_session_info(void) +{ + int count, i, short_len; + char *tok; + struct lttng_session *sessions; + + if (opt_session_uuid != NULL) { + short_len = sizeof(short_str_uuid) - 1; + /* Shorten uuid */ + tok = strchr(opt_session_uuid, '.'); + if (strlen(tok + 1) == short_len) { + memcpy(short_str_uuid, tok + 1, short_len); + short_str_uuid[short_len] = '\0'; + } + + /* Get long real uuid_t from session daemon */ + count = lttng_list_sessions(&sessions); + for (i = 0; i < count; i++) { + uuid_unparse(sessions[i].uuid, long_str_uuid); + if (strncmp(long_str_uuid, short_str_uuid, 8) == 0) { + uuid_copy(current_uuid, sessions[i].uuid); + break; + } + } + } + + if (opt_session_name != NULL) { + session_name = strndup(opt_session_name, NAME_MAX); + } +} + +/* + * shorten_uuid + * + * Small function to shorten the 37 bytes long uuid_t + * string representation to 8 characters. + */ +static void shorten_uuid(char *long_u, char *short_u) +{ + memcpy(short_u, long_u, 8); + short_u[UUID_SHORT_STR_LEN - 1] = '\0'; +} + +/* + * set_session_uuid + * + * Set current session uuid to the current flow of + * command(s) using the already shorten uuid or + * current full uuid. + */ +static int set_session_uuid(void) +{ + int ret, count, i; + char str_uuid[37]; + struct lttng_session *sessions; + + if (!uuid_is_null(current_uuid)) { + lttng_set_current_session_uuid(¤t_uuid); + goto end; + } + + count = lttng_list_sessions(&sessions); + if (count < 0) { + ret = count; + goto error; + } + + for (i = 0; i < count; i++) { + uuid_unparse(sessions[i].uuid, str_uuid); + if (strncmp(str_uuid, short_str_uuid, 8) == 0) { + lttng_set_current_session_uuid(&sessions[i].uuid); + break; + } + } + + free(sessions); + +end: + return 0; + +error: + return ret; +} + +/* + * process_opt_list_traces + * + * Get list of all traces for a specific session uuid. + */ +static int process_opt_list_traces(void) +{ + int ret, i; + struct lttng_trace *traces; + + ret = lttng_list_traces(¤t_uuid, &traces); + if (ret < 0) { + goto error; + } + + MSG("Userspace traces:"); + for (i = 0; i < ret; i++) { + if (traces[i].type == USERSPACE) { + MSG("\t%d) %s (pid: %d): %s", + i, traces[i].name, traces[i].pid, + get_cmdline_by_pid(traces[i].pid)); + } else { + break; + } + } + + MSG("Kernel traces:"); + for (;i < ret; i++) { + if (traces[i].type == KERNEL) { + MSG("\t%d) %s", i, traces[i].name); + } + } + + free(traces); + +error: + return ret; +} + +/* + * process_opt_create_session + * + * Create a new session using the name pass + * to the command line. + */ +static int process_opt_create_session(void) +{ + int ret; + uuid_t session_id; + char str_uuid[37]; + char name[NAME_MAX]; + time_t rawtime; + struct tm *timeinfo; + + /* Auto session creation */ + if (opt_create_session == 0) { + time(&rawtime); + timeinfo = localtime(&rawtime); + strftime(name, sizeof(name), "%Y%m%d-%H%M%S", timeinfo); + session_name = strndup(name, sizeof(name)); + } + + ret = lttng_create_session(session_name, &session_id); + if (ret < 0) { + goto error; + } + + uuid_unparse(session_id, str_uuid); + uuid_copy(current_uuid, session_id); + shorten_uuid(str_uuid, short_str_uuid); + + MSG("Session UUID created: %s.%s", session_name, short_str_uuid); + +error: + return ret; } /* @@ -92,21 +338,26 @@ end: static int process_opt_list_sessions(void) { int ret, count, i; + char tmp_short_uuid[9]; + char str_uuid[37]; struct lttng_session *sess; count = lttng_list_sessions(&sess); + DBG("Session count %d", count); if (count < 0) { ret = count; goto error; } - MSG("Available sessions [Name (uuid)]:"); + MSG("Available sessions (UUIDs):"); for (i = 0; i < count; i++) { - MSG("\tName: %s (uuid: %s)", sess[i].name, sess[i].uuid); + uuid_unparse(sess[i].uuid, str_uuid); + shorten_uuid(str_uuid, tmp_short_uuid); + MSG(" %d) %s.%s", i+1, sess[i].name, tmp_short_uuid); } free(sess); - MSG("\nTo select a session, use --session UUID."); + MSG("\nTo select a session, use -s, --session UUID."); return 0; @@ -124,9 +375,7 @@ static int process_opt_list_apps(void) { int i, ret, count; pid_t *pids; - FILE *fp; - char path[24]; /* Can't go bigger than /proc/65535/cmdline */ - char cmdline[PATH_MAX]; + char *cmdline; count = lttng_ust_list_apps(&pids); if (count < 0) { @@ -136,15 +385,13 @@ static int process_opt_list_apps(void) MSG("LTTng UST traceable application [name (pid)]:"); for (i=0; i < count; i++) { - snprintf(path, sizeof(path), "/proc/%d/cmdline", pids[i]); - fp = fopen(path, "r"); - if (fp == NULL) { + cmdline = get_cmdline_by_pid(pids[i]); + if (cmdline == NULL) { MSG("\t(not running) (%d)", pids[i]); continue; } - ret = fread(cmdline, 1, sizeof(cmdline), fp); MSG("\t%s (%d)", cmdline, pids[i]); - fclose(fp); + free(cmdline); } /* Allocated by lttng_ust_list_apps() */ @@ -156,6 +403,71 @@ error: return ret; } +/* + * get_cmdline_by_pid + * + * Get command line from /proc for a specific pid. + * + * On success, return an allocated string pointer pointing to + * the proc cmdline. + * On error, return NULL. + */ +static char *get_cmdline_by_pid(pid_t pid) +{ + int ret; + FILE *fp; + char *cmdline = NULL; + char path[24]; /* Can't go bigger than /proc/65535/cmdline */ + + snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); + fp = fopen(path, "r"); + if (fp == NULL) { + goto end; + } + + /* Caller must free() *cmdline */ + cmdline = malloc(PATH_MAX); + ret = fread(cmdline, 1, PATH_MAX, fp); + fclose(fp); + +end: + return cmdline; +} + +/* + * validate_options + * + * Make sure that all options passed to the command line + * are compatible with each others. + * + * On error, return -1 + * On success, return 0 + */ +static int validate_options(void) +{ + /* Conflicting command */ + if (opt_start_trace && opt_stop_trace) { + ERR("Can't use --start and --stop together."); + goto error; + /* If no PID specified and trace_kernel is off */ + } else if ((opt_trace_pid == 0 && opt_trace_kernel == 0) && + (opt_create_trace || opt_start_trace || opt_stop_trace)) { + ERR("Please specify a PID using -p, --pid PID."); + goto error; + } else if (opt_session_uuid && opt_create_session) { + ERR("Please don't use -s and -c together. Useless action."); + goto error; + } else if (opt_list_traces && opt_session_uuid == NULL) { + ERR("Can't use -t without -s, --session option."); + goto error; + } + + return 0; + +error: + return -1; +} + /* * spawn_sessiond * @@ -290,26 +602,33 @@ end: */ static void sighandler(int sig) { - DBG("%d received", sig); switch (sig) { case SIGTERM: + DBG("SIGTERM catched"); clean_exit(EXIT_FAILURE); break; case SIGCHLD: /* Notify is done */ + DBG("SIGCHLD catched"); break; default: + DBG("Unknown signal %d catched", sig); break; } return; } + /* * clean_exit */ void clean_exit(int code) { DBG("Clean exit"); + if (session_name) { + free(session_name); + } + exit(code); } @@ -328,13 +647,18 @@ int main(int argc, char *argv[]) } ret = parse_args(argc, (const char **) argv); + if (ret < 0) { + clean_exit(EXIT_FAILURE); + } + + ret = validate_options(); if (ret < 0) { return EXIT_FAILURE; } ret = set_signal_handler(); if (ret < 0) { - return ret; + clean_exit(ret); } if (opt_tracing_group != NULL) { @@ -347,7 +671,7 @@ int main(int argc, char *argv[]) DBG("Kernel tracing activated"); if (getuid() != 0) { ERR("%s must be setuid root", progname); - return -EPERM; + clean_exit(-EPERM); } } @@ -355,13 +679,15 @@ int main(int argc, char *argv[]) * If no, a daemon will be spawned. */ if (opt_no_sessiond == 0 && (check_ltt_sessiond() < 0)) { - return EXIT_FAILURE; + clean_exit(EXIT_FAILURE); } ret = process_client_opt(); if (ret < 0) { - return ret; + clean_exit(ret); } + clean_exit(0); + return 0; }