LTTNG_HIDDEN int mi_lttng_event_function_entry(struct mi_writer *writer, struct lttng_event *event) { int ret; ret = mi_lttng_writer_open_element(writer, config_element_attributes); if (ret) { goto end; } ret = mi_lttng_writer_open_element(writer, config_element_probe_attributes); if (ret) { goto end; } /* event probe symbol_name */ ret = mi_lttng_writer_write_element_string(writer, config_element_symbol_name, event->attr.ftrace.symbol_name); if (ret) { goto end; } /* Close function_attributes and attributes */ ret = mi_lttng_close_multi_element(writer, 2); end: return ret; }
/* * List tracker PID(s) of session and domain. */ static int list_tracker_pids(void) { int ret = 0; int enabled; int *pids = NULL; size_t nr_pids; ret = lttng_list_tracker_pids(handle, &enabled, &pids, &nr_pids); if (ret) { return ret; } if (enabled) { int i; _MSG("PID tracker: ["); /* Mi tracker_pid element*/ if (writer) { /* Open tracker_pid and targets elements */ ret = mi_lttng_pid_tracker_open(writer); if (ret) { goto end; } } for (i = 0; i < nr_pids; i++) { if (i) { _MSG(","); } _MSG(" %d", pids[i]); /* Mi */ if (writer) { ret = mi_lttng_pid_target(writer, pids[i], 0); if (ret) { goto end; } } } _MSG(" ]\n\n"); /* Mi close tracker_pid and targets */ if (writer) { ret = mi_lttng_close_multi_element(writer,2); if (ret) { goto end; } } } end: free(pids); return ret; }
LTTNG_HIDDEN int mi_lttng_event_function_probe(struct mi_writer *writer, struct lttng_event *event) { int ret; ret = mi_lttng_writer_open_element(writer, config_element_attributes); if (ret) { goto end; } ret = mi_lttng_writer_open_element(writer, config_element_probe_attributes); if (ret) { goto end; } if (event->attr.probe.addr != 0) { /* event probe address */ ret = mi_lttng_writer_write_element_unsigned_int(writer, config_element_address, event->attr.probe.addr); if (ret) { goto end; } } else { /* event probe offset */ ret = mi_lttng_writer_write_element_unsigned_int(writer, config_element_offset, event->attr.probe.offset); if (ret) { goto end; } /* event probe symbol_name */ ret = mi_lttng_writer_write_element_string(writer, config_element_symbol_name, event->attr.probe.symbol_name); if (ret) { goto end; } } /* Close probe_attributes and attributes */ ret = mi_lttng_close_multi_element(writer, 2); end: return ret; }
/* * Machine interface * Print a list of kernel events */ static int mi_list_kernel_events(struct lttng_event *events, int count, struct lttng_domain *domain) { int ret, i; /* Open domains element */ ret = mi_lttng_domains_open(writer); if (ret) { goto end; } /* Write domain */ ret = mi_lttng_domain(writer, domain, 1); if (ret) { goto end; } /* Open events */ ret = mi_lttng_events_open(writer); if (ret) { goto end; } for (i = 0; i < count; i++) { ret = mi_lttng_event(writer, &events[i], 0, handle->domain.type); if (ret) { goto end; } } /* close events, domain and domains */ ret = mi_lttng_close_multi_element(writer, 3); if (ret) { goto end; } end: return ret; }
/* * Print the necessary mi for a session and name. */ static int mi_print(char *session_name) { int ret; assert(writer); assert(session_name); /* * Open a sessions element * This is purely for validation purpose */ ret = mi_lttng_sessions_open(writer); if (ret) { goto end; } /* Open a session element */ ret = mi_lttng_writer_open_element(writer, config_element_session); if (ret) { goto end; } /* Session name */ ret = mi_lttng_writer_write_element_string(writer , config_element_name, session_name); if (ret) { goto end; } /* Close session and sessions element */ ret = mi_lttng_close_multi_element(writer, 2); if (ret) { goto end; } end: return ret; }
static int handle_command(const char **argv) { int ret = CMD_SUCCESS, i = 0, argc, command_ret = CMD_SUCCESS; struct cmd_struct *cmd; if (argv == NULL || (!opt_ctrl_url && opt_data_url) || (opt_ctrl_url && !opt_data_url)) { usage(stderr); command_ret = CMD_ERROR; goto end; } argc = count_arguments(argv); cmd = &actions[i]; while (cmd->func != NULL) { /* Find command */ if (strcmp(argv[0], cmd->name) == 0) { if (lttng_opt_mi) { /* Action element */ ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_action); if (ret) { ret = CMD_ERROR; goto end; } /* Name of the action */ ret = mi_lttng_writer_write_element_string(writer, config_element_name, argv[0]); if (ret) { ret = CMD_ERROR; goto end; } /* Open output element */ ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output); if (ret) { ret = CMD_ERROR; goto end; } } command_ret = cmd->func(argc, argv); if (lttng_opt_mi) { /* Close output and action element */ ret = mi_lttng_close_multi_element(writer, 2); if (ret) { ret = CMD_ERROR; goto end; } } goto end; } i++; cmd = &actions[i]; } ret = CMD_UNDEFINED; end: /* Overwrite ret if an error occurred in cmd->func() */ ret = command_ret ? command_ret : ret; return ret; }
/* * The 'destroy <options>' first level command */ int cmd_destroy(int argc, const char **argv) { int opt; int ret = CMD_SUCCESS , i, command_ret = CMD_SUCCESS, success = 1; static poptContext pc; char *session_name = NULL; const char *leftover = NULL; struct lttng_session *sessions; int count; int found; pc = poptGetContext(NULL, argc, argv, long_options, 0); poptReadDefaultConfig(pc, 0); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_HELP: SHOW_HELP(); break; case OPT_LIST_OPTIONS: list_cmd_options(stdout, long_options); break; default: ret = CMD_UNDEFINED; break; } goto end; } /* Mi preparation */ if (lttng_opt_mi) { writer = 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_destroy); if (ret) { ret = CMD_ERROR; goto end; } /* Open output element */ ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output); if (ret) { ret = CMD_ERROR; goto end; } /* For validation and semantic purpose we open a sessions element */ ret = mi_lttng_sessions_open(writer); if (ret) { ret = CMD_ERROR; goto end; } } /* Recuperate all sessions for further operation */ count = lttng_list_sessions(&sessions); if (count < 0) { ERR("%s", lttng_strerror(count)); command_ret = CMD_ERROR; success = 0; goto mi_closing; } /* Ignore session name in case all sessions are to be destroyed */ if (opt_destroy_all) { command_ret = destroy_all_sessions(sessions, count); if (command_ret) { success = 0; } } else { opt_session_name = (char *) poptGetArg(pc); if (!opt_session_name) { /* No session name specified, lookup default */ session_name = get_session_name(); if (session_name == NULL) { command_ret = CMD_ERROR; success = 0; goto mi_closing; } } else { session_name = opt_session_name; } /* Find the corresponding lttng_session struct */ found = 0; for (i = 0; i < count; i++) { if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) { found = 1; command_ret = destroy_session(&sessions[i]); if (command_ret) { success = 0; } } } if (!found) { ERR("Session name %s not found", session_name); command_ret = LTTNG_ERR_SESS_NOT_FOUND; success = 0; goto mi_closing; } } leftover = poptGetArg(pc); if (leftover) { ERR("Unknown argument: %s", leftover); ret = CMD_ERROR; success = 0; goto mi_closing; } mi_closing: /* Mi closing */ if (lttng_opt_mi) { /* Close sessions and output element element */ ret = mi_lttng_close_multi_element(writer, 2); if (ret) { ret = CMD_ERROR; goto end; } /* Success ? */ ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto end; } /* Command element close */ ret = mi_lttng_writer_command_close(writer); if (ret) { ret = CMD_ERROR; goto end; } } 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) { free(session_name); } /* Overwrite ret if an error occurred during destroy_session/all */ ret = command_ret ? command_ret : ret; poptFreeContext(pc); return ret; }
/* * disable_events * * Disabling event using the lttng API. */ static int disable_events(char *session_name) { int ret = CMD_SUCCESS, warn = 0, command_ret = CMD_SUCCESS; int enabled = 1, success = 1; char *event_name, *channel_name = NULL; struct lttng_domain dom; struct lttng_event event; memset(&dom, 0, sizeof(dom)); /* Create lttng domain */ if (opt_kernel) { dom.type = LTTNG_DOMAIN_KERNEL; } else if (opt_userspace) { dom.type = LTTNG_DOMAIN_UST; } else if (opt_jul) { dom.type = LTTNG_DOMAIN_JUL; } else if (opt_log4j) { dom.type = LTTNG_DOMAIN_LOG4J; } else if (opt_python) { dom.type = LTTNG_DOMAIN_PYTHON; } else { /* Checked by the caller. */ assert(0); } channel_name = opt_channel_name; handle = lttng_create_handle(session_name, &dom); if (handle == NULL) { ret = -1; goto error; } /* Mi print the channel and open the events element */ if (lttng_opt_mi) { ret = mi_lttng_writer_open_element(writer, config_element_channel); if (ret) { ret = CMD_ERROR; goto end; } ret = mi_lttng_writer_write_element_string(writer, config_element_name, print_channel_name(channel_name)); if (ret) { ret = CMD_ERROR; goto end; } /* Open events element */ ret = mi_lttng_writer_open_element(writer, config_element_events); if (ret) { ret = CMD_ERROR; goto end; } } memset(&event, 0, sizeof(event)); /* Set default loglevel to any/unknown */ event.loglevel = -1; /* opt_event_type contain the event type to disable at this point */ event.type = opt_event_type; if (opt_disable_all) { command_ret = lttng_disable_event_ext(handle, &event, channel_name, NULL); if (command_ret < 0) { ERR("%s", lttng_strerror(command_ret)); enabled = 1; success = 0; } else { enabled = 0; success = 1; MSG("All %s events of type %s are disabled in channel %s", get_domain_str(dom.type), print_event_type(opt_event_type), print_channel_name(channel_name)); } if (lttng_opt_mi) { ret = mi_print_event("*", enabled, success); if (ret) { ret = CMD_ERROR; goto error; } } } else { /* Strip event list */ event_name = strtok(opt_event_list, ","); while (event_name != NULL) { DBG("Disabling event %s", event_name); strncpy(event.name, event_name, sizeof(event.name)); event.name[sizeof(event.name) - 1] = '\0'; command_ret = lttng_disable_event_ext(handle, &event, channel_name, NULL); if (command_ret < 0) { ERR("%s of type %s : %s (channel %s, session %s)", event_name, print_event_type(opt_event_type), lttng_strerror(command_ret), command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ? print_raw_channel_name(channel_name) : print_channel_name(channel_name), session_name); warn = 1; success = 0; /* * If an error occurred we assume that the event is still * enabled. */ enabled = 1; } else { MSG("%s %s of type %s disabled in channel %s for session %s", get_domain_str(dom.type), event_name, print_event_type(opt_event_type), print_channel_name(channel_name), session_name); success = 1; enabled = 0; } if (lttng_opt_mi) { ret = mi_print_event(event_name, enabled, success); if (ret) { ret = CMD_ERROR; goto error; } } /* Next event */ event_name = strtok(NULL, ","); } } end: if (lttng_opt_mi) { /* Close events element and channel element */ ret = mi_lttng_close_multi_element(writer, 2); if (ret) { ret = CMD_ERROR; } } error: /* if there is already an error preserve it */ if (warn && !ret) { ret = CMD_WARNING; } /* Overwrite ret if an error occurred */ ret = command_ret ? command_ret : ret; lttng_destroy_handle(handle); return ret; }
/* * Machine interface * List all ust event with their fields */ static int mi_list_ust_event_fields(struct lttng_event_field *fields, int count, struct lttng_domain *domain) { int ret, i; pid_t cur_pid = 0; char *cmdline = NULL; int pid_element_open = 0; int event_element_open = 0; struct lttng_event cur_event; /* Open domains element */ ret = mi_lttng_domains_open(writer); if (ret) { goto end; } /* Write domain */ ret = mi_lttng_domain(writer, domain, 1); if (ret) { goto end; } /* Open pids element */ ret = mi_lttng_pids_open(writer); if (ret) { goto end; } for (i = 0; i < count; i++) { if (cur_pid != fields[i].event.pid) { if (pid_element_open) { if (event_element_open) { /* Close the previous field element and event. */ ret = mi_lttng_close_multi_element(writer, 2); if (ret) { goto end; } event_element_open = 0; } /* Close the previous events, pid element */ ret = mi_lttng_close_multi_element(writer, 2); if (ret) { goto end; } pid_element_open = 0; } cur_pid = fields[i].event.pid; cmdline = get_cmdline_by_pid(cur_pid); if (!pid_element_open) { /* Open and write a pid element */ ret = mi_lttng_pid(writer, cur_pid, cmdline, 1); if (ret) { goto error; } /* Open events element */ ret = mi_lttng_events_open(writer); if (ret) { goto error; } pid_element_open = 1; } free(cmdline); /* Wipe current event since we are about to print a new PID. */ memset(&cur_event, 0, sizeof(cur_event)); } if (strcmp(cur_event.name, fields[i].event.name) != 0) { if (event_element_open) { /* Close the previous fields element and the previous event */ ret = mi_lttng_close_multi_element(writer, 2); if (ret) { goto end; } event_element_open = 0; } memcpy(&cur_event, &fields[i].event, sizeof(cur_event)); if (!event_element_open) { /* Open and write the event */ ret = mi_lttng_event(writer, &cur_event, 1, handle->domain.type); if (ret) { goto end; } /* Open a fields element */ ret = mi_lttng_event_fields_open(writer); if (ret) { goto end; } event_element_open = 1; } } /* Print the event_field */ ret = mi_lttng_event_field(writer, &fields[i]); if (ret) { goto end; } } /* Close pids, domain, domains */ ret = mi_lttng_close_multi_element(writer, 3); end: return ret; error: free(cmdline); return ret; }
/* * Machine interface * Jul and ust event listing */ static int mi_list_agent_ust_events(struct lttng_event *events, int count, struct lttng_domain *domain) { int ret, i; pid_t cur_pid = 0; char *cmdline = NULL; int pid_element_open = 0; /* Open domains element */ ret = mi_lttng_domains_open(writer); if (ret) { goto end; } /* Write domain */ ret = mi_lttng_domain(writer, domain, 1); if (ret) { goto end; } /* Open pids element */ ret = mi_lttng_pids_open(writer); if (ret) { goto end; } for (i = 0; i < count; i++) { if (cur_pid != events[i].pid) { if (pid_element_open) { /* Close the previous events and pid element */ ret = mi_lttng_close_multi_element(writer, 2); if (ret) { goto end; } pid_element_open = 0; } cur_pid = events[i].pid; cmdline = get_cmdline_by_pid(cur_pid); if (!cmdline) { ret = CMD_ERROR; goto end; } if (!pid_element_open) { /* Open and write a pid element */ ret = mi_lttng_pid(writer, cur_pid, cmdline, 1); if (ret) { goto error; } /* Open events element */ ret = mi_lttng_events_open(writer); if (ret) { goto error; } pid_element_open = 1; } free(cmdline); } /* Write an event */ ret = mi_lttng_event(writer, &events[i], 0, handle->domain.type); if (ret) { goto end; } } /* Close pids */ ret = mi_lttng_writer_close_element(writer); if (ret) { goto end; } /* Close domain, domains */ ret = mi_lttng_close_multi_element(writer, 2); end: return ret; error: free(cmdline); return ret; }
/* * The 'list <options>' first level command */ int cmd_list(int argc, const char **argv) { int opt, ret = CMD_SUCCESS; const char *session_name; static poptContext pc; struct lttng_domain domain; struct lttng_domain *domains = NULL; memset(&domain, 0, sizeof(domain)); if (argc < 1) { usage(stderr); ret = CMD_ERROR; goto end; } pc = poptGetContext(NULL, argc, argv, long_options, 0); poptReadDefaultConfig(pc, 0); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_HELP: usage(stdout); goto end; case OPT_USERSPACE: opt_userspace = 1; break; case OPT_LIST_OPTIONS: list_cmd_options(stdout, long_options); goto end; default: usage(stderr); ret = CMD_UNDEFINED; goto end; } } /* Mi check */ if (lttng_opt_mi) { writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); if (!writer) { ret = CMD_ERROR; goto end; } /* Open command element */ ret = mi_lttng_writer_command_open(writer, mi_lttng_element_command_list); if (ret) { ret = CMD_ERROR; goto end; } /* Open output element */ ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output); if (ret) { ret = CMD_ERROR; goto end; } } /* Get session name (trailing argument) */ session_name = poptGetArg(pc); DBG2("Session name: %s", session_name); if (opt_kernel) { domain.type = LTTNG_DOMAIN_KERNEL; } else if (opt_userspace) { DBG2("Listing userspace global domain"); domain.type = LTTNG_DOMAIN_UST; } else if (opt_jul) { DBG2("Listing JUL domain"); domain.type = LTTNG_DOMAIN_JUL; } else if (opt_log4j) { domain.type = LTTNG_DOMAIN_LOG4J; } else if (opt_python) { domain.type = LTTNG_DOMAIN_PYTHON; } if (!opt_kernel && opt_syscall) { WARN("--syscall will only work with the Kernel domain (-k)"); ret = CMD_ERROR; goto end; } if (opt_kernel || opt_userspace || opt_jul || opt_log4j || opt_python) { handle = lttng_create_handle(session_name, &domain); if (handle == NULL) { ret = CMD_FATAL; goto end; } } if (session_name == NULL) { if (!opt_kernel && !opt_userspace && !opt_jul && !opt_log4j && !opt_python) { ret = list_sessions(NULL); if (ret) { goto end; } } if (opt_kernel) { if (opt_syscall) { ret = list_syscalls(); if (ret) { goto end; } } else { ret = list_kernel_events(); if (ret) { goto end; } } } if (opt_userspace) { if (opt_fields) { ret = list_ust_event_fields(); } else { ret = list_ust_events(); } if (ret) { goto end; } } if (opt_jul || opt_log4j || opt_python) { ret = list_agent_events(); if (ret) { goto end; } } } else { /* List session attributes */ if (lttng_opt_mi) { /* Open element sessions * Present for xml consistency */ ret = mi_lttng_sessions_open(writer); if (ret) { goto end; } } /* MI: the ouptut of list_sessions is an unclosed session element */ ret = list_sessions(session_name); if (ret) { goto end; } /* Domain listing */ if (opt_domain) { ret = list_domains(session_name); goto end; } /* Channel listing */ if (opt_kernel || opt_userspace) { if (lttng_opt_mi) { /* Add of domains and domain element for xml * consistency and validation */ ret = mi_lttng_domains_open(writer); if (ret) { goto end; } /* Open domain and leave it open for * nested channels printing */ ret = mi_lttng_domain(writer, &domain, 1); if (ret) { goto end; } } ret = list_tracker_pids(); if (ret) { goto end; } ret = list_channels(opt_channel); if (ret) { goto end; } if (lttng_opt_mi) { /* Close domain and domain element */ ret = mi_lttng_close_multi_element(writer, 2); } if (ret) { goto end; } } else { int i, nb_domain; /* We want all domain(s) */ nb_domain = lttng_list_domains(session_name, &domains); if (nb_domain < 0) { ret = CMD_ERROR; ERR("%s", lttng_strerror(nb_domain)); goto end; } if (lttng_opt_mi) { ret = mi_lttng_domains_open(writer); if (ret) { ret = CMD_ERROR; goto end; } } for (i = 0; i < nb_domain; i++) { switch (domains[i].type) { case LTTNG_DOMAIN_KERNEL: MSG("=== Domain: Kernel ===\n"); break; case LTTNG_DOMAIN_UST: MSG("=== Domain: UST global ===\n"); MSG("Buffer type: %s\n", domains[i].buf_type == LTTNG_BUFFER_PER_PID ? "per PID" : "per UID"); break; case LTTNG_DOMAIN_JUL: MSG("=== Domain: JUL (Java Util Logging) ===\n"); break; case LTTNG_DOMAIN_LOG4J: MSG("=== Domain: LOG4j (Logging for Java) ===\n"); break; case LTTNG_DOMAIN_PYTHON: MSG("=== Domain: Python (logging) ===\n"); break; default: MSG("=== Domain: Unimplemented ===\n"); break; } if (lttng_opt_mi) { ret = mi_lttng_domain(writer, &domains[i], 1); if (ret) { ret = CMD_ERROR; goto end; } } /* Clean handle before creating a new one */ if (handle) { lttng_destroy_handle(handle); } handle = lttng_create_handle(session_name, &domains[i]); if (handle == NULL) { ret = CMD_FATAL; goto end; } if (domains[i].type == LTTNG_DOMAIN_JUL || domains[i].type == LTTNG_DOMAIN_LOG4J || domains[i].type == LTTNG_DOMAIN_PYTHON) { ret = list_session_agent_events(); if (ret) { goto end; } continue; } switch (domains[i].type) { case LTTNG_DOMAIN_KERNEL: case LTTNG_DOMAIN_UST: ret = list_tracker_pids(); if (ret) { goto end; } break; default: break; } ret = list_channels(opt_channel); if (ret) { goto end; } if (lttng_opt_mi) { /* Close domain element */ ret = mi_lttng_writer_close_element(writer); if (ret) { ret = CMD_ERROR; goto end; } } } if (lttng_opt_mi) { /* Close the domains, session and sessions element */ ret = mi_lttng_close_multi_element(writer, 3); if (ret) { ret = CMD_ERROR; goto end; } } } } /* Mi closing */ if (lttng_opt_mi) { /* Close output element */ ret = mi_lttng_writer_close_element(writer); if (ret) { ret = CMD_ERROR; goto end; } /* Command element close */ ret = mi_lttng_writer_command_close(writer); if (ret) { ret = CMD_ERROR; goto end; } } end: /* Mi clean-up */ if (writer && mi_lttng_writer_destroy(writer)) { /* Preserve original error code */ ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL; } free(domains); if (handle) { lttng_destroy_handle(handle); } poptFreeContext(pc); return ret; }
/* * cmd_stop * * The 'stop <options>' first level command */ int cmd_stop(int argc, const char **argv) { int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1; static poptContext pc; const char *leftover = NULL; pc = poptGetContext(NULL, argc, argv, long_options, 0); poptReadDefaultConfig(pc, 0); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_HELP: SHOW_HELP(); goto end; case OPT_LIST_OPTIONS: list_cmd_options(stdout, long_options); goto end; default: ret = CMD_UNDEFINED; goto end; } } /* Mi check */ if (lttng_opt_mi) { writer = 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_stop); if (ret) { ret = CMD_ERROR; goto end; } /* Open output element */ ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output); if (ret) { ret = CMD_ERROR; goto end; } /* * Open sessions element * For validation */ ret = mi_lttng_writer_open_element(writer, config_element_sessions); if (ret) { ret = CMD_ERROR; goto end; } } opt_session_name = (char*) poptGetArg(pc); leftover = poptGetArg(pc); if (leftover) { ERR("Unknown argument: %s", leftover); ret = CMD_ERROR; goto end; } command_ret = stop_tracing(); if (command_ret) { success = 0; } /* Mi closing */ if (lttng_opt_mi) { /* Close sessions and output element */ ret = mi_lttng_close_multi_element(writer, 2); if (ret) { ret = CMD_ERROR; goto end; } /* Success ? */ ret = mi_lttng_writer_write_element_bool(writer, mi_lttng_element_command_success, success); if (ret) { ret = CMD_ERROR; goto end; } /* Command element close */ ret = mi_lttng_writer_command_close(writer); if (ret) { ret = CMD_ERROR; goto end; } } end: /* Mi clean-up */ if (writer && mi_lttng_writer_destroy(writer)) { /* Preserve original error code */ ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL; } /* Overwrite ret if an error occurred in stop_tracing() */ ret = command_ret ? command_ret : ret; poptFreeContext(pc); return ret; }