X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fbin%2Flttng%2Fcommands%2Fenable_events.cpp;h=e6f6274fb140c9b2b56c7db3f1b78703b09acc51;hb=8884bbc1ce31fa2fc4085a430c4f253e1dd95f14;hp=5c655bb4332cc9177e261e1d4b2d38daa18025ec;hpb=28ab034a2c3582d07d3423d2d746731f87d3969f;p=lttng-tools.git diff --git a/src/bin/lttng/commands/enable_events.cpp b/src/bin/lttng/commands/enable_events.cpp index 5c655bb43..e6f6274fb 100644 --- a/src/bin/lttng/commands/enable_events.cpp +++ b/src/bin/lttng/commands/enable_events.cpp @@ -8,6 +8,7 @@ #define _LGPL_SOURCE #include #include +#include #include #include #include @@ -35,22 +36,37 @@ #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255" #endif -static int opt_event_type; -static const char *opt_loglevel; -static int opt_loglevel_type; -static int opt_kernel; -static char *opt_session_name; -static int opt_userspace; -static int opt_jul; -static int opt_log4j; -static int opt_python; -static int opt_enable_all; -static char *opt_probe; -static char *opt_userspace_probe; -static char *opt_function; -static char *opt_channel_name; -static char *opt_filter; -static char *opt_exclude; +namespace { +void _mi_lttng_writer_deleter_func(mi_writer *writer) +{ + if (writer && mi_lttng_writer_destroy(writer)) { + LTTNG_THROW_ERROR("Failed to destroy mi_writer instance"); + } +} + +using mi_writer_uptr = std::unique_ptr< + mi_writer, + lttng::memory::create_deleter_class::deleter>; + +int opt_event_type; +const char *opt_loglevel; +int opt_loglevel_type; +int opt_kernel; +char *opt_session_name; +int opt_userspace; +int opt_jul; +int opt_log4j; +int opt_python; +int opt_enable_all; +char *opt_probe; +char *opt_userspace_probe; +char *opt_function; +char *opt_channel_name; +char *opt_filter; +char *opt_exclude; + +struct lttng_handle *handle; +mi_writer_uptr writer; #ifdef LTTNG_EMBED_HELP static const char help_msg[] = @@ -73,37 +89,40 @@ enum { OPT_EXCLUDE, }; -static struct lttng_handle *handle; -static struct mi_writer *writer; - -static struct poptOption long_options[] = { +struct poptOption long_options[] = { /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ - { "help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0 }, - { "session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0 }, - { "all", 'a', POPT_ARG_VAL, &opt_enable_all, 1, 0, 0 }, - { "channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0 }, - { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0 }, - { "userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0 }, - { "jul", 'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0 }, - { "log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, 0, 0 }, - { "python", 'p', POPT_ARG_VAL, &opt_python, 1, 0, 0 }, - { "tracepoint", 0, POPT_ARG_NONE, 0, OPT_TRACEPOINT, 0, 0 }, - { "probe", 0, POPT_ARG_STRING, &opt_probe, OPT_PROBE, 0, 0 }, - { "userspace-probe", 0, POPT_ARG_STRING, &opt_userspace_probe, OPT_USERSPACE_PROBE, 0, 0 }, - { "function", 0, POPT_ARG_STRING, &opt_function, OPT_FUNCTION, 0, 0 }, - { "syscall", 0, POPT_ARG_NONE, 0, OPT_SYSCALL, 0, 0 }, - { "loglevel", 0, POPT_ARG_STRING, 0, OPT_LOGLEVEL, 0, 0 }, - { "loglevel-only", 0, POPT_ARG_STRING, 0, OPT_LOGLEVEL_ONLY, 0, 0 }, - { "list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL }, - { "filter", 'f', POPT_ARG_STRING, &opt_filter, OPT_FILTER, 0, 0 }, - { "exclude", 'x', POPT_ARG_STRING, &opt_exclude, OPT_EXCLUDE, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0 } + { "help", 'h', POPT_ARG_NONE, nullptr, OPT_HELP, nullptr, nullptr }, + { "session", 's', POPT_ARG_STRING, &opt_session_name, 0, nullptr, nullptr }, + { "all", 'a', POPT_ARG_VAL, &opt_enable_all, 1, nullptr, nullptr }, + { "channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, nullptr, nullptr }, + { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, nullptr, nullptr }, + { "userspace", 'u', POPT_ARG_NONE, nullptr, OPT_USERSPACE, nullptr, nullptr }, + { "jul", 'j', POPT_ARG_VAL, &opt_jul, 1, nullptr, nullptr }, + { "log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, nullptr, nullptr }, + { "python", 'p', POPT_ARG_VAL, &opt_python, 1, nullptr, nullptr }, + { "tracepoint", 0, POPT_ARG_NONE, nullptr, OPT_TRACEPOINT, nullptr, nullptr }, + { "probe", 0, POPT_ARG_STRING, &opt_probe, OPT_PROBE, nullptr, nullptr }, + { "userspace-probe", + 0, + POPT_ARG_STRING, + &opt_userspace_probe, + OPT_USERSPACE_PROBE, + nullptr, + nullptr }, + { "function", 0, POPT_ARG_STRING, &opt_function, OPT_FUNCTION, nullptr, nullptr }, + { "syscall", 0, POPT_ARG_NONE, nullptr, OPT_SYSCALL, nullptr, nullptr }, + { "loglevel", 0, POPT_ARG_STRING, nullptr, OPT_LOGLEVEL, nullptr, nullptr }, + { "loglevel-only", 0, POPT_ARG_STRING, nullptr, OPT_LOGLEVEL_ONLY, nullptr, nullptr }, + { "list-options", 0, POPT_ARG_NONE, nullptr, OPT_LIST_OPTIONS, nullptr, nullptr }, + { "filter", 'f', POPT_ARG_STRING, &opt_filter, OPT_FILTER, nullptr, nullptr }, + { "exclude", 'x', POPT_ARG_STRING, &opt_exclude, OPT_EXCLUDE, nullptr, nullptr }, + { nullptr, 0, 0, nullptr, 0, nullptr, nullptr } }; /* * Parse probe options. */ -static int parse_probe_opts(struct lttng_event *ev, char *opt) +int parse_probe_opts(struct lttng_event *ev, char *opt) { int ret = CMD_SUCCESS; int match; @@ -111,7 +130,7 @@ static int parse_probe_opts(struct lttng_event *ev, char *opt) #define S_HEX_LEN_SCANF_IS_A_BROKEN_API "18" /* 18 is (19 - 1) (\0 is extra) */ char name[LTTNG_SYMBOL_NAME_LEN]; - if (opt == NULL) { + if (opt == nullptr) { ret = CMD_ERROR; goto end; } @@ -131,7 +150,7 @@ static int parse_probe_opts(struct lttng_event *ev, char *opt) ret = CMD_ERROR; goto end; } - ev->attr.probe.offset = strtoull(s_hex, NULL, 0); + ev->attr.probe.offset = strtoull(s_hex, nullptr, 0); DBG("probe offset %" PRIu64, ev->attr.probe.offset); ev->attr.probe.addr = 0; goto end; @@ -164,7 +183,7 @@ static int parse_probe_opts(struct lttng_event *ev, char *opt) ret = CMD_ERROR; goto end; } - ev->attr.probe.addr = strtoull(s_hex, NULL, 0); + ev->attr.probe.addr = strtoull(s_hex, nullptr, 0); DBG("probe addr %" PRIu64, ev->attr.probe.addr); ev->attr.probe.offset = 0; memset(ev->attr.probe.symbol_name, 0, LTTNG_SYMBOL_NAME_LEN); @@ -178,12 +197,12 @@ end: return ret; } -static const char *print_channel_name(const char *name) +const char *print_channel_name(const char *name) { return name ?: DEFAULT_CHANNEL_NAME; } -static const char *print_raw_channel_name(const char *name) +const char *print_raw_channel_name(const char *name) { return name ?: ""; } @@ -191,7 +210,7 @@ static const char *print_raw_channel_name(const char *name) /* * Mi print exlcusion list */ -static int mi_print_exclusion(const struct lttng_dynamic_pointer_array *exclusions) +int mi_print_exclusion(const struct lttng_dynamic_pointer_array *exclusions) { int ret; size_t i; @@ -204,7 +223,7 @@ static int mi_print_exclusion(const struct lttng_dynamic_pointer_array *exclusio goto end; } - ret = mi_lttng_writer_open_element(writer, config_element_exclusions); + ret = mi_lttng_writer_open_element(writer.get(), config_element_exclusions); if (ret) { goto end; } @@ -214,14 +233,14 @@ static int mi_print_exclusion(const struct lttng_dynamic_pointer_array *exclusio (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions, i); ret = mi_lttng_writer_write_element_string( - writer, config_element_exclusion, exclusion); + writer.get(), config_element_exclusion, exclusion); if (ret) { goto end; } } /* Close exclusions element */ - ret = mi_lttng_writer_close_element(writer); + ret = mi_lttng_writer_close_element(writer.get()); end: return ret; @@ -230,7 +249,7 @@ end: /* * Return allocated string for pretty-printing exclusion names. */ -static char *print_exclusions(const struct lttng_dynamic_pointer_array *exclusions) +char *print_exclusions(const struct lttng_dynamic_pointer_array *exclusions) { int length = 0; size_t i; @@ -253,7 +272,7 @@ static char *print_exclusions(const struct lttng_dynamic_pointer_array *exclusio length += sizeof(preamble); ret = calloc(length); if (!ret) { - return NULL; + return nullptr; } strncpy(ret, preamble, length); @@ -272,7 +291,7 @@ static char *print_exclusions(const struct lttng_dynamic_pointer_array *exclusio return ret; } -static int check_exclusion_subsets(const char *event_name, const char *exclusion) +int check_exclusion_subsets(const char *event_name, const char *exclusion) { bool warn = false; int ret = 0; @@ -335,55 +354,9 @@ end: return ret; } -int validate_exclusion_list(const char *event_name, - const struct lttng_dynamic_pointer_array *exclusions) -{ - int ret; - - /* Event name must be a valid globbing pattern to allow exclusions. */ - if (!strutils_is_star_glob_pattern(event_name)) { - ERR("Event %s: Exclusions can only be used with a globbing pattern", event_name); - goto error; - } - - /* - * If the event name is a star-at-end only globbing pattern, - * then we can validate the individual exclusions. Otherwise - * all exclusions are passed to the session daemon. - */ - if (strutils_is_star_at_the_end_only_glob_pattern(event_name)) { - size_t i, num_exclusions; - - num_exclusions = lttng_dynamic_pointer_array_get_count(exclusions); - - for (i = 0; i < num_exclusions; i++) { - const char *exclusion = - (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions, - i); - - if (!strutils_is_star_glob_pattern(exclusion) || - strutils_is_star_at_the_end_only_glob_pattern(exclusion)) { - ret = check_exclusion_subsets(event_name, exclusion); - if (ret) { - goto error; - } - } - } - } - - ret = 0; - goto end; - -error: - ret = -1; - -end: - return ret; -} - -static int create_exclusion_list_and_validate(const char *event_name, - const char *exclusions_arg, - struct lttng_dynamic_pointer_array *exclusions) +int create_exclusion_list_and_validate(const char *event_name, + const char *exclusions_arg, + struct lttng_dynamic_pointer_array *exclusions) { int ret = 0; @@ -407,8 +380,8 @@ end: return ret; } -static void warn_on_truncated_exclusion_names(const struct lttng_dynamic_pointer_array *exclusions, - int *warn) +void warn_on_truncated_exclusion_names(const struct lttng_dynamic_pointer_array *exclusions, + int *warn) { size_t i; const size_t num_exclusions = lttng_dynamic_pointer_array_get_count(exclusions); @@ -428,17 +401,17 @@ static void warn_on_truncated_exclusion_names(const struct lttng_dynamic_pointer * Enabling event using the lttng API. * Note: in case of error only the last error code will be return. */ -static int enable_events(char *session_name, char *event_list) +int enable_events(char *session_name, char *event_list) { int ret = CMD_SUCCESS, command_ret = CMD_SUCCESS; int error_holder = CMD_SUCCESS, warn = 0, error = 0, success = 1; - char *event_name, *channel_name = NULL; + char *event_name, *channel_name = nullptr; struct lttng_event *ev; struct lttng_domain dom = {}; struct lttng_dynamic_pointer_array exclusions; - struct lttng_userspace_probe_location *uprobe_loc = NULL; + struct lttng_userspace_probe_location *uprobe_loc = nullptr; - lttng_dynamic_pointer_array_init(&exclusions, NULL); + lttng_dynamic_pointer_array_init(&exclusions, nullptr); ev = lttng_event_create(); if (!ev) { @@ -522,7 +495,7 @@ static int enable_events(char *session_name, char *event_list) channel_name = opt_channel_name; handle = lttng_create_handle(session_name, &dom); - if (handle == NULL) { + if (handle == nullptr) { ret = -1; goto error; } @@ -530,7 +503,7 @@ static int enable_events(char *session_name, char *event_list) /* Prepare Mi */ if (lttng_opt_mi) { /* Open a events element */ - ret = mi_lttng_writer_open_element(writer, config_element_events); + ret = mi_lttng_writer_open_element(writer.get(), config_element_events); if (ret) { ret = CMD_ERROR; goto error; @@ -614,7 +587,7 @@ static int enable_events(char *session_name, char *event_list) handle, ev, channel_name, - NULL, + nullptr, lttng_dynamic_pointer_array_get_count(&exclusions), (char **) exclusions.array.buffer.data); if (ret < 0) { @@ -790,7 +763,7 @@ static int enable_events(char *session_name, char *event_list) ev->enabled = 0; success = 0; } - ret = mi_lttng_event(writer, ev, 1, handle->domain.type); + ret = mi_lttng_event(writer.get(), ev, 1, handle->domain.type); if (ret) { ret = CMD_ERROR; goto error; @@ -805,14 +778,14 @@ static int enable_events(char *session_name, char *event_list) /* Success ? */ ret = mi_lttng_writer_write_element_bool( - writer, mi_lttng_element_command_success, success); + writer.get(), mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto error; } /* Close event element */ - ret = mi_lttng_writer_close_element(writer); + ret = mi_lttng_writer_close_element(writer.get()); if (ret) { ret = CMD_ERROR; goto error; @@ -824,7 +797,7 @@ static int enable_events(char *session_name, char *event_list) /* Strip event list */ event_name = strtok(event_list, ","); - while (event_name != NULL) { + while (event_name != nullptr) { /* Copy name and type of the event */ strncpy(ev->name, event_name, LTTNG_SYMBOL_NAME_LEN); ev->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; @@ -839,7 +812,7 @@ static int enable_events(char *session_name, char *event_list) switch (opt_event_type) { case LTTNG_EVENT_ALL: /* Enable tracepoints and syscalls */ /* If event name differs from *, select tracepoint. */ - if (strcmp(ev->name, "*")) { + if (strcmp(ev->name, "*") != 0) { ev->type = LTTNG_EVENT_TRACEPOINT; } break; @@ -882,7 +855,7 @@ static int enable_events(char *session_name, char *event_list) } /* Ownership of the uprobe location was transferred to the event. */ - uprobe_loc = NULL; + uprobe_loc = nullptr; break; case LTTNG_EVENT_FUNCTION: ret = parse_probe_opts(ev, opt_function); @@ -1024,7 +997,7 @@ static int enable_events(char *session_name, char *event_list) handle, ev, channel_name, - NULL, + nullptr, lttng_dynamic_pointer_array_get_count(&exclusions), (char **) exclusions.array.buffer.data); exclusion_string = print_exclusions(&exclusions); @@ -1182,7 +1155,7 @@ static int enable_events(char *session_name, char *event_list) ev->enabled = 1; } - ret = mi_lttng_event(writer, ev, 1, handle->domain.type); + ret = mi_lttng_event(writer.get(), ev, 1, handle->domain.type); if (ret) { ret = CMD_ERROR; goto error; @@ -1197,14 +1170,14 @@ static int enable_events(char *session_name, char *event_list) /* Success ? */ ret = mi_lttng_writer_write_element_bool( - writer, mi_lttng_element_command_success, success); + writer.get(), mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto end; } /* Close event element */ - ret = mi_lttng_writer_close_element(writer); + ret = mi_lttng_writer_close_element(writer.get()); if (ret) { ret = CMD_ERROR; goto end; @@ -1212,7 +1185,7 @@ static int enable_events(char *session_name, char *event_list) } /* Next event */ - event_name = strtok(NULL, ","); + event_name = strtok(nullptr, ","); /* Reset warn, error and success */ success = 1; } @@ -1221,7 +1194,7 @@ end: /* Close Mi */ if (lttng_opt_mi) { /* Close events element */ - ret = mi_lttng_writer_close_element(writer); + ret = mi_lttng_writer_close_element(writer.get()); if (ret) { ret = CMD_ERROR; goto error; @@ -1247,6 +1220,54 @@ error: return ret; } +} /* namespace */ + +int validate_exclusion_list(const char *event_name, + const struct lttng_dynamic_pointer_array *exclusions) +{ + int ret; + + /* Event name must be a valid globbing pattern to allow exclusions. */ + if (!strutils_is_star_glob_pattern(event_name)) { + ERR("Event %s: Exclusions can only be used with a globbing pattern", event_name); + goto error; + } + + /* + * If the event name is a star-at-end only globbing pattern, + * then we can validate the individual exclusions. Otherwise + * all exclusions are passed to the session daemon. + */ + if (strutils_is_star_at_the_end_only_glob_pattern(event_name)) { + size_t i, num_exclusions; + + num_exclusions = lttng_dynamic_pointer_array_get_count(exclusions); + + for (i = 0; i < num_exclusions; i++) { + const char *exclusion = + (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions, + i); + + if (!strutils_is_star_glob_pattern(exclusion) || + strutils_is_star_at_the_end_only_glob_pattern(exclusion)) { + ret = check_exclusion_subsets(event_name, exclusion); + if (ret) { + goto error; + } + } + } + } + + ret = 0; + goto end; + +error: + ret = -1; + +end: + return ret; +} + /* * Add event to trace session */ @@ -1254,13 +1275,13 @@ int cmd_enable_events(int argc, const char **argv) { int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1; static poptContext pc; - char *session_name = NULL; - char *event_list = NULL; - const char *arg_event_list = NULL; - const char *leftover = NULL; + char *session_name = nullptr; + char *event_list = nullptr; + const char *arg_event_list = nullptr; + const char *leftover = nullptr; int event_type = -1; - pc = poptGetContext(NULL, argc, argv, long_options, 0); + pc = poptGetContext(nullptr, argc, argv, long_options, 0); poptReadDefaultConfig(pc, 0); /* Default event type */ @@ -1330,21 +1351,22 @@ int cmd_enable_events(int argc, const char **argv) /* Mi check */ if (lttng_opt_mi) { - writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); + writer = mi_writer_uptr(mi_lttng_writer_create(fileno(stdout), lttng_opt_mi)); if (!writer) { ret = -LTTNG_ERR_NOMEM; goto end; } /* Open command element */ - ret = mi_lttng_writer_command_open(writer, mi_lttng_element_command_enable_event); + ret = mi_lttng_writer_command_open(writer.get(), + mi_lttng_element_command_enable_event); if (ret) { ret = CMD_ERROR; goto end; } /* Open output element */ - ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output); + ret = mi_lttng_writer_open_element(writer.get(), mi_lttng_element_command_output); if (ret) { ret = CMD_ERROR; goto end; @@ -1352,7 +1374,7 @@ int cmd_enable_events(int argc, const char **argv) } arg_event_list = poptGetArg(pc); - if (arg_event_list == NULL && opt_enable_all == 0) { + if (arg_event_list == nullptr && opt_enable_all == 0) { ERR("Missing event name(s)."); ret = CMD_ERROR; goto end; @@ -1360,7 +1382,7 @@ int cmd_enable_events(int argc, const char **argv) if (opt_enable_all == 0) { event_list = strdup(arg_event_list); - if (event_list == NULL) { + if (event_list == nullptr) { PERROR("Failed to copy event name(s)"); ret = CMD_ERROR; goto end; @@ -1376,7 +1398,7 @@ int cmd_enable_events(int argc, const char **argv) if (!opt_session_name) { session_name = get_session_name(); - if (session_name == NULL) { + if (session_name == nullptr) { command_ret = CMD_ERROR; success = 0; goto mi_closing; @@ -1395,21 +1417,21 @@ mi_closing: /* Mi closing */ if (lttng_opt_mi) { /* Close output element */ - ret = mi_lttng_writer_close_element(writer); + ret = mi_lttng_writer_close_element(writer.get()); if (ret) { ret = CMD_ERROR; goto end; } ret = mi_lttng_writer_write_element_bool( - writer, mi_lttng_element_command_success, success); + writer.get(), mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto end; } /* Command element close */ - ret = mi_lttng_writer_command_close(writer); + ret = mi_lttng_writer_command_close(writer.get()); if (ret) { ret = CMD_ERROR; goto end; @@ -1417,13 +1439,7 @@ mi_closing: } end: - /* Mi clean-up */ - if (writer && mi_lttng_writer_destroy(writer)) { - /* Preserve original error code */ - ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL; - } - - if (opt_session_name == NULL) { + if (opt_session_name == nullptr) { free(session_name); }