X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng%2Fcommands%2Ftrack-untrack.c;h=3073996a9f6d19acfa257e87b1075959a9da3521;hp=52442cc1361b2e8d1d0574a35f3812996bb735a8;hb=dc1c9a44fba1a368c283186e531c217206f5e816;hpb=ccf10263bcd2ca4667b9e1fc4dab64a3c8d8c4d8 diff --git a/src/bin/lttng/commands/track-untrack.c b/src/bin/lttng/commands/track-untrack.c index 52442cc13..3073996a9 100644 --- a/src/bin/lttng/commands/track-untrack.c +++ b/src/bin/lttng/commands/track-untrack.c @@ -16,7 +16,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define _GNU_SOURCE #define _LGPL_SOURCE #include #include @@ -26,6 +25,7 @@ #include #include #include +#include #include @@ -64,28 +64,6 @@ static struct poptOption long_options[] = { { 0, 0, 0, 0, 0, 0, 0, }, }; -/* - * usage - */ -static void usage(FILE *ofp, const char *cmd_str) -{ - fprintf(ofp, "usage: lttng %s [-k|-u] [OPTIONS]\n", cmd_str); - fprintf(ofp, "\n"); - fprintf(ofp, "If no session is given (-s), the context is added to\n"); - fprintf(ofp, "the current sesssion. Exactly one domain (-k or -u)\n"); - fprintf(ofp, "must be specified.\n"); - fprintf(ofp, "\n"); - fprintf(ofp, "Options:\n"); - fprintf(ofp, " -h, --help Show this help.\n"); - fprintf(ofp, " --list-options Simple listing of options.\n"); - fprintf(ofp, " -s, --session NAME Apply to session name.\n"); - fprintf(ofp, " -k, --kernel Apply to the kernel tracer.\n"); - fprintf(ofp, " -u, --userspace Apply to the user-space tracer.\n"); - fprintf(ofp, " -p, --pid [PID] Process ID tracker. Leave PID empty when used with --all.\n"); - fprintf(ofp, " -a, --all All PIDs (use with --pid).\n"); - fprintf(ofp, "\n"); -} - static int parse_pid_string(const char *_pid_string, int all, int **_pid_list, int *nr_pids) @@ -96,6 +74,7 @@ int parse_pid_string(const char *_pid_string, int count = 0; int *pid_list = NULL; char *pid_string = NULL; + char *endptr; if (all && _pid_string) { ERR("An empty PID string is expected with --all"); @@ -108,7 +87,7 @@ int parse_pid_string(const char *_pid_string, goto error; } if (all) { - pid_list = zmalloc(sizeof(*_pid_list)); + pid_list = zmalloc(sizeof(*pid_list)); if (!pid_list) { ERR("Out of memory"); retval = CMD_ERROR; @@ -132,13 +111,16 @@ int parse_pid_string(const char *_pid_string, while (one_pid_str != NULL) { unsigned long v; - v = strtoul(one_pid_str, NULL, 10); + errno = 0; + v = strtoul(one_pid_str, &endptr, 10); if ((v == 0 && errno == EINVAL) - || (v == ULONG_MAX && errno == ERANGE)) { + || (v == ULONG_MAX && errno == ERANGE) + || (*one_pid_str != '\0' && *endptr != '\0')){ ERR("Error parsing PID %s", one_pid_str); retval = CMD_ERROR; goto error; } + if ((long) v > INT_MAX || (int) v < 0) { ERR("Invalid PID value %ld", (long) v); retval = CMD_ERROR; @@ -149,6 +131,11 @@ int parse_pid_string(const char *_pid_string, /* For next loop */ one_pid_str = strtok_r(NULL, ",", &iter); } + if (count == 0) { + ERR("Fatal error occurred when parsing pid string"); + retval = CMD_ERROR; + goto error; + } free(pid_string); /* Identity of delimiter has been lost in first pass. */ @@ -167,7 +154,7 @@ int parse_pid_string(const char *_pid_string, goto error; } - /* Copy */ + /* Reparse string and populate the pid list. */ count = 0; one_pid_str = strtok_r(pid_string, ",", &iter); while (one_pid_str != NULL) { @@ -194,23 +181,24 @@ end: } static -int track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str, +enum cmd_error_code track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str, const char *session_name, const char *pid_string, int all, struct mi_writer *writer) { - int ret, retval = CMD_SUCCESS, i; + int ret, success = 1 , i; + enum cmd_error_code retval = CMD_SUCCESS; int *pid_list = NULL; int nr_pids; struct lttng_domain dom; struct lttng_handle *handle = NULL; - int (*lib_func)(struct lttng_handle *handle, int pid); + int (*cmd_func)(struct lttng_handle *handle, int pid); switch (cmd_type) { case CMD_TRACK: - lib_func = lttng_track_pid; + cmd_func = lttng_track_pid; break; case CMD_UNTRACK: - lib_func = lttng_untrack_pid; + cmd_func = lttng_untrack_pid; break; default: ERR("Unknown command"); @@ -224,15 +212,13 @@ int track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str, } else if (opt_userspace) { dom.type = LTTNG_DOMAIN_UST; } else { - print_missing_domain(); - ret = CMD_ERROR; - goto end; + /* Checked by the caller. */ + assert(0); } ret = parse_pid_string(pid_string, all, &pid_list, &nr_pids); if (ret != CMD_SUCCESS) { ERR("Error parsing PID string"); - usage(stderr, cmd_str); retval = CMD_ERROR; goto end; } @@ -244,26 +230,74 @@ int track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str, } if (writer) { - /* Open pids element */ - ret = mi_lttng_writer_open_element(writer, config_element_pids); + /* Open process element */ + ret = mi_lttng_targets_open(writer); if (ret) { retval = CMD_ERROR; goto end; } } - /* TODO: MI */ for (i = 0; i < nr_pids; i++) { DBG("%s PID %d", cmd_str, pid_list[i]); - ret = lib_func(handle, pid_list[i]); + ret = cmd_func(handle, pid_list[i]); if (ret) { - retval = CMD_ERROR; - goto end; + switch (-ret) { + case LTTNG_ERR_PID_TRACKED: + WARN("PID %i already tracked in session %s", + pid_list[i], session_name); + success = 1; + retval = CMD_SUCCESS; + break; + case LTTNG_ERR_PID_NOT_TRACKED: + WARN("PID %i not tracked in session %s", + pid_list[i], session_name); + success = 1; + retval = CMD_SUCCESS; + break; + default: + ERR("%s", lttng_strerror(ret)); + success = 0; + retval = CMD_ERROR; + break; + } + } else { + if (pid_list[i] != -1) { + MSG("PID %i %sed in session %s", + pid_list[i], cmd_str, + session_name); + } else { + MSG("All PIDs %sed in session %s", + cmd_str, session_name); + } + success = 1; + } + + /* Mi */ + if (writer) { + ret = mi_lttng_pid_target(writer, pid_list[i], 1); + if (ret) { + retval = CMD_ERROR; + goto end; + } + + ret = mi_lttng_writer_write_element_bool(writer, + mi_lttng_element_success, success); + if (ret) { + retval = CMD_ERROR; + goto end; + } + + ret = mi_lttng_writer_close_element(writer); + if (ret) { + retval = CMD_ERROR; + goto end; + } } } if (writer) { - /* Close pids element */ + /* Close targets element */ ret = mi_lttng_writer_close_element(writer); if (ret) { retval = CMD_ERROR; @@ -271,7 +305,6 @@ int track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str, } } - /* SUCCESS */ end: if (handle) { lttng_destroy_handle(handle); @@ -298,17 +331,17 @@ const char *get_mi_element_command(enum cmd_type cmd_type) */ static int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, - int argc, const char **argv) + int argc, const char **argv, const char *help_msg) { - int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS; + int opt, ret = 0; + enum cmd_error_code command_ret = CMD_SUCCESS; int success = 1; static poptContext pc; char *session_name = NULL; struct mi_writer *writer = NULL; if (argc < 1) { - usage(stderr, cmd_str); - ret = CMD_ERROR; + command_ret = CMD_ERROR; goto end; } @@ -318,7 +351,7 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_HELP: - usage(stdout, cmd_str); + SHOW_HELP(); goto end; case OPT_LIST_OPTIONS: list_cmd_options(stdout, long_options); @@ -328,23 +361,21 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, opt_pid = 1; break; default: - usage(stderr, cmd_str); - ret = CMD_UNDEFINED; + command_ret = CMD_UNDEFINED; goto end; } } - if (!(opt_userspace ^ opt_kernel)) { - ERR("Exactly one of -u or -k needs to be specified."); - usage(stderr, cmd_str); - ret = CMD_ERROR; + ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace); + if (ret) { + command_ret = CMD_ERROR; goto end; } if (!opt_session_name) { session_name = get_session_name(); if (session_name == NULL) { - ret = CMD_ERROR; + command_ret = CMD_ERROR; goto end; } } else { @@ -354,8 +385,7 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, /* Currently only PID tracker is supported */ if (!opt_pid) { ERR("Please specify at least one tracker with its expected arguments"); - usage(stderr, cmd_str); - ret = CMD_ERROR; + command_ret = CMD_ERROR; goto end; } @@ -363,7 +393,7 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, if (lttng_opt_mi) { writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); if (!writer) { - ret = CMD_ERROR; + command_ret = CMD_ERROR; goto end; } } @@ -373,7 +403,7 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, ret = mi_lttng_writer_command_open(writer, get_mi_element_command(cmd_type)); if (ret) { - ret = CMD_ERROR; + command_ret = CMD_ERROR; goto end; } @@ -381,7 +411,7 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output); if (ret) { - ret = CMD_ERROR; + command_ret = CMD_ERROR; goto end; } } @@ -389,7 +419,7 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, command_ret = track_untrack_pid(cmd_type, cmd_str, session_name, opt_pid_string, opt_all, writer); - if (command_ret) { + if (command_ret != CMD_SUCCESS) { success = 0; } @@ -398,7 +428,7 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, /* Close output element */ ret = mi_lttng_writer_close_element(writer); if (ret) { - ret = CMD_ERROR; + command_ret = CMD_ERROR; goto end; } @@ -406,14 +436,14 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_command_success, success); if (ret) { - ret = CMD_ERROR; + command_ret = CMD_ERROR; goto end; } /* Command element close */ ret = mi_lttng_writer_command_close(writer); if (ret) { - ret = CMD_ERROR; + command_ret = CMD_ERROR; goto end; } } @@ -426,22 +456,35 @@ end: /* Mi clean-up */ if (writer && mi_lttng_writer_destroy(writer)) { /* Preserve original error code */ - ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL; + command_ret = CMD_ERROR; } - /* Overwrite ret if an error occurred during track() */ - ret = command_ret ? command_ret : ret; - poptFreeContext(pc); - return ret; + return (int) command_ret; } int cmd_track(int argc, const char **argv) { - return cmd_track_untrack(CMD_TRACK, "track", argc, argv); + static const char *help_msg = +#ifdef LTTNG_EMBED_HELP +#include +#else + NULL +#endif + ; + + return cmd_track_untrack(CMD_TRACK, "track", argc, argv, help_msg); } int cmd_untrack(int argc, const char **argv) { - return cmd_track_untrack(CMD_UNTRACK, "untrack", argc, argv); + static const char *help_msg = +#ifdef LTTNG_EMBED_HELP +#include +#else + NULL +#endif + ; + + return cmd_track_untrack(CMD_UNTRACK, "untrack", argc, argv, help_msg); }