X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.cpp;h=47c049b319ed9a9f3dbc31f4dda935f8ff31007d;hb=c9e313bc594f40a86eed237dce222c0fc99c957f;hp=5bfa64530ec53262b1b6d0f4bcd80cd57d814a33;hpb=999af9c1150784f8676c6fce0764772d2314854a;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/cmd.cpp b/src/bin/lttng-sessiond/cmd.cpp index 5bfa64530..47c049b31 100644 --- a/src/bin/lttng-sessiond/cmd.cpp +++ b/src/bin/lttng-sessiond/cmd.cpp @@ -15,60 +15,61 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include +#include #include -#include +#include #include -#include +#include #include -#include -#include +#include +#include +#include #include -#include +#include #include -#include -#include -#include +#include +#include +#include #include -#include -#include - -#include "agent-thread.h" -#include "agent.h" -#include "buffer-registry.h" -#include "channel.h" -#include "cmd.h" -#include "consumer.h" -#include "event-notifier-error-accounting.h" -#include "event.h" -#include "health-sessiond.h" -#include "kernel-consumer.h" -#include "kernel.h" -#include "lttng-sessiond.h" -#include "lttng-syscall.h" -#include "notification-thread-commands.h" -#include "notification-thread.h" -#include "rotate.h" -#include "rotation-thread.h" -#include "session.h" -#include "timer.h" -#include "tracker.h" -#include "utils.h" +#include +#include + +#include "agent-thread.hpp" +#include "agent.hpp" +#include "buffer-registry.hpp" +#include "channel.hpp" +#include "cmd.hpp" +#include "consumer.hpp" +#include "event-notifier-error-accounting.hpp" +#include "event.hpp" +#include "health-sessiond.hpp" +#include "kernel-consumer.hpp" +#include "kernel.hpp" +#include "lttng-sessiond.hpp" +#include "lttng-syscall.hpp" +#include "notification-thread-commands.hpp" +#include "notification-thread.hpp" +#include "rotate.hpp" +#include "rotation-thread.hpp" +#include "session.hpp" +#include "timer.hpp" +#include "tracker.hpp" +#include "utils.hpp" /* Sleep for 100ms between each check for the shm path's deletion. */ #define SESSION_DESTROY_SHM_PATH_CHECK_DELAY_US 100000 @@ -121,7 +122,8 @@ static int cmd_enable_event_internal(struct ltt_session *session, struct lttng_bytecode *filter, struct lttng_event_exclusion *exclusion, int wpipe); -static int cmd_enable_channel_internal(struct ltt_session *session, +static enum lttng_error_code cmd_enable_channel_internal( + struct ltt_session *session, const struct lttng_domain *domain, const struct lttng_channel *_attr, int wpipe); @@ -295,150 +297,96 @@ end: return ret; } -static int append_extended_info(const char *filter_expression, - struct lttng_event_exclusion *exclusion, - struct lttng_userspace_probe_location *probe_location, - struct lttng_payload *payload) -{ - int ret = 0; - size_t filter_len = 0; - size_t nb_exclusions = 0; - size_t userspace_probe_location_len = 0; - struct lttcomm_event_extended_header extended_header = {}; - struct lttcomm_event_extended_header *p_extended_header; - const size_t original_payload_size = payload->buffer.size; - - ret = lttng_dynamic_buffer_append(&payload->buffer, &extended_header, - sizeof(extended_header)); - if (ret) { - goto end; - } - - if (filter_expression) { - filter_len = strlen(filter_expression) + 1; - ret = lttng_dynamic_buffer_append(&payload->buffer, - filter_expression, filter_len); - if (ret) { - goto end; - } - } - - if (exclusion) { - const size_t len = exclusion->count * LTTNG_SYMBOL_NAME_LEN; - - nb_exclusions = exclusion->count; - - ret = lttng_dynamic_buffer_append( - &payload->buffer, &exclusion->names, len); - if (ret) { - goto end; - } - } - - if (probe_location) { - const size_t size_before_probe = payload->buffer.size; - - ret = lttng_userspace_probe_location_serialize(probe_location, - payload); - if (ret < 0) { - ret = -1; - goto end; - } - - userspace_probe_location_len = - payload->buffer.size - size_before_probe; - } - - /* Set header fields */ - p_extended_header = (struct lttcomm_event_extended_header *) - (payload->buffer.data + original_payload_size); - - p_extended_header->filter_len = filter_len; - p_extended_header->nb_exclusions = nb_exclusions; - p_extended_header->userspace_probe_location_len = - userspace_probe_location_len; - - ret = 0; -end: - return ret; -} - /* * Create a list of agent domain events. * * Return number of events in list on success or else a negative value. */ -static int list_lttng_agent_events(struct agent *agt, - struct lttng_payload *payload) +static enum lttng_error_code list_lttng_agent_events( + struct agent *agt, struct lttng_payload *reply_payload, + unsigned int *nb_events) { - int nb_events = 0, ret = 0; - const struct agent_event *agent_event; + enum lttng_error_code ret_code; + int ret = 0; + unsigned int local_nb_events = 0; + struct agent_event *event; struct lttng_ht_iter iter; + unsigned long agent_event_count; - LTTNG_ASSERT(agt); + assert(agt); + assert(reply_payload); DBG3("Listing agent events"); rcu_read_lock(); - cds_lfht_for_each_entry ( - agt->events->ht, &iter.iter, agent_event, node.node) { - struct lttng_event event {}; + agent_event_count = lttng_ht_get_count(agt->events); + if (agent_event_count == 0) { + /* Early exit. */ + goto end; + } - event.loglevel_type = agent_event->loglevel_type; - event.loglevel = agent_event->loglevel_value; - event.enabled = AGENT_EVENT_IS_ENABLED(agent_event); + if (agent_event_count > UINT_MAX) { + ret_code = LTTNG_ERR_OVERFLOW; + goto error; + } - ret = lttng_strncpy(event.name, agent_event->name, sizeof(event.name)); - if (ret) { - /* Internal error, invalid name. */ - ERR("Invalid event name while listing agent events: '%s' exceeds the maximal allowed length of %zu bytes", - agent_event->name, sizeof(event.name)); - ret = -LTTNG_ERR_UNK; - goto end; - } + local_nb_events = (unsigned int) agent_event_count; - ret = lttng_dynamic_buffer_append( - &payload->buffer, &event, sizeof(event)); - if (ret) { - ERR("Failed to append event to payload"); - ret = -LTTNG_ERR_NOMEM; - goto end; + cds_lfht_for_each_entry(agt->events->ht, &iter.iter, event, node.node) { + struct lttng_event *tmp_event = lttng_event_create(); + + if (!tmp_event) { + ret_code = LTTNG_ERR_NOMEM; + goto error; } - nb_events++; - } + if (lttng_strncpy(tmp_event->name, event->name, sizeof(tmp_event->name))) { + lttng_event_destroy(tmp_event); + ret_code = LTTNG_ERR_FATAL; + goto error; + } + + tmp_event->name[sizeof(tmp_event->name) - 1] = '\0'; + tmp_event->enabled = !!event->enabled_count; + tmp_event->loglevel = event->loglevel_value; + tmp_event->loglevel_type = event->loglevel_type; - cds_lfht_for_each_entry ( - agt->events->ht, &iter.iter, agent_event, node.node) { - /* Append extended info. */ - ret = append_extended_info(agent_event->filter_expression, NULL, - NULL, payload); + ret = lttng_event_serialize(tmp_event, 0, NULL, + event->filter_expression, 0, NULL, reply_payload); + lttng_event_destroy(tmp_event); if (ret) { - ERR("Failed to append extended event info to payload"); - ret = -LTTNG_ERR_NOMEM; - goto end; + ret_code = LTTNG_ERR_FATAL; + goto error; } } - ret = nb_events; end: + ret_code = LTTNG_OK; + *nb_events = local_nb_events; +error: rcu_read_unlock(); - return ret; + return ret_code; } /* * Create a list of ust global domain events. */ -static int list_lttng_ust_global_events(char *channel_name, +static enum lttng_error_code list_lttng_ust_global_events(char *channel_name, struct ltt_ust_domain_global *ust_global, - struct lttng_payload *payload) + struct lttng_payload *reply_payload, + unsigned int *nb_events) { - int ret = 0; - unsigned int nb_events = 0; + enum lttng_error_code ret_code; + int ret; struct lttng_ht_iter iter; - const struct lttng_ht_node_str *node; - const struct ltt_ust_channel *uchan; - const struct ltt_ust_event *uevent; + struct lttng_ht_node_str *node; + struct ltt_ust_channel *uchan; + struct ltt_ust_event *uevent; + unsigned long channel_event_count; + unsigned int local_nb_events = 0; + + assert(reply_payload); + assert(nb_events); DBG("Listing UST global events for channel %s", channel_name); @@ -447,158 +395,184 @@ static int list_lttng_ust_global_events(char *channel_name, lttng_ht_lookup(ust_global->channels, (void *) channel_name, &iter); node = lttng_ht_iter_get_node_str(&iter); if (node == NULL) { - ret = LTTNG_ERR_UST_CHAN_NOT_FOUND; - goto end; + ret_code = LTTNG_ERR_UST_CHAN_NOT_FOUND; + goto error; } uchan = caa_container_of(&node->node, struct ltt_ust_channel, node.node); - DBG3("Listing UST global events"); + channel_event_count = lttng_ht_get_count(uchan->events); + if (channel_event_count == 0) { + /* Early exit. */ + ret_code = LTTNG_OK; + goto end; + } + + if (channel_event_count > UINT_MAX) { + ret_code = LTTNG_ERR_OVERFLOW; + goto error; + } + + local_nb_events = (unsigned int) channel_event_count; + + DBG3("Listing UST global %d events", *nb_events); cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) { - struct lttng_event event = {}; + struct lttng_event *tmp_event = NULL; if (uevent->internal) { + /* This event should remain hidden from clients */ + local_nb_events--; continue; } - ret = lttng_strncpy(event.name, uevent->attr.name, sizeof(event.name)); - if (ret) { - /* Internal error, invalid name. */ - ERR("Invalid event name while listing user space tracer events: '%s' exceeds the maximal allowed length of %zu bytes", - uevent->attr.name, sizeof(event.name)); - ret = -LTTNG_ERR_UNK; - goto end; + tmp_event = lttng_event_create(); + if (!tmp_event) { + ret_code = LTTNG_ERR_NOMEM; + goto error; } - event.enabled = uevent->enabled; + if (lttng_strncpy(tmp_event->name, uevent->attr.name, + LTTNG_SYMBOL_NAME_LEN)) { + ret_code = LTTNG_ERR_FATAL; + lttng_event_destroy(tmp_event); + goto error; + } + + tmp_event->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; + tmp_event->enabled = uevent->enabled; switch (uevent->attr.instrumentation) { case LTTNG_UST_ABI_TRACEPOINT: - event.type = LTTNG_EVENT_TRACEPOINT; + tmp_event->type = LTTNG_EVENT_TRACEPOINT; break; case LTTNG_UST_ABI_PROBE: - event.type = LTTNG_EVENT_PROBE; + tmp_event->type = LTTNG_EVENT_PROBE; break; case LTTNG_UST_ABI_FUNCTION: - event.type = LTTNG_EVENT_FUNCTION; + tmp_event->type = LTTNG_EVENT_FUNCTION; break; } - event.loglevel = uevent->attr.loglevel; + tmp_event->loglevel = uevent->attr.loglevel; switch (uevent->attr.loglevel_type) { case LTTNG_UST_ABI_LOGLEVEL_ALL: - event.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; + tmp_event->loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; break; case LTTNG_UST_ABI_LOGLEVEL_RANGE: - event.loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE; + tmp_event->loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE; break; case LTTNG_UST_ABI_LOGLEVEL_SINGLE: - event.loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE; + tmp_event->loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE; break; } - if (uevent->filter) { - event.filter = 1; + tmp_event->filter = 1; } - if (uevent->exclusion) { - event.exclusion = 1; + tmp_event->exclusion = 1; } - ret = lttng_dynamic_buffer_append(&payload->buffer, &event, sizeof(event)); - if (ret) { - ERR("Failed to append event to payload"); - ret = -LTTNG_ERR_NOMEM; - goto end; - } - - nb_events++; - } - - cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) { - /* Append extended info. */ - ret = append_extended_info(uevent->filter_expression, - uevent->exclusion, NULL, payload); + /* + * We do not care about the filter bytecode and the fd from the + * userspace_probe_location. + */ + ret = lttng_event_serialize(tmp_event, uevent->exclusion ? uevent->exclusion->count : 0, + uevent->exclusion ? (char **) uevent->exclusion ->names : NULL, + uevent->filter_expression, 0, NULL, reply_payload); + lttng_event_destroy(tmp_event); if (ret) { - ERR("Failed to append extended event info to payload"); - ret = -LTTNG_ERR_FATAL; - goto end; + ret_code = LTTNG_ERR_FATAL; + goto error; } } - ret = nb_events; end: + /* nb_events is already set at this point. */ + ret_code = LTTNG_OK; + *nb_events = local_nb_events; +error: rcu_read_unlock(); - return ret; + return ret_code; } /* * Fill lttng_event array of all kernel events in the channel. */ -static int list_lttng_kernel_events(char *channel_name, +static enum lttng_error_code list_lttng_kernel_events(char *channel_name, struct ltt_kernel_session *kernel_session, - struct lttng_payload *payload) + struct lttng_payload *reply_payload, + unsigned int *nb_events) { + enum lttng_error_code ret_code; int ret; - unsigned int nb_event; - const struct ltt_kernel_event *kevent; - const struct ltt_kernel_channel *kchan; + struct ltt_kernel_event *event; + struct ltt_kernel_channel *kchan; + + assert(reply_payload); kchan = trace_kernel_get_channel_by_name(channel_name, kernel_session); if (kchan == NULL) { - ret = LTTNG_ERR_KERN_CHAN_NOT_FOUND; - goto error; + ret_code = LTTNG_ERR_KERN_CHAN_NOT_FOUND; + goto end; } - nb_event = kchan->event_count; + *nb_events = kchan->event_count; DBG("Listing events for channel %s", kchan->channel->name); + if (*nb_events == 0) { + ret_code = LTTNG_OK; + goto end; + } + /* Kernel channels */ - cds_list_for_each_entry(kevent, &kchan->events_list.head , list) { - struct lttng_event event = {}; + cds_list_for_each_entry(event, &kchan->events_list.head , list) { + struct lttng_event *tmp_event = lttng_event_create(); - ret = lttng_strncpy(event.name, kevent->event->name, sizeof(event.name)); - if (ret) { - /* Internal error, invalid name. */ - ERR("Invalid event name while listing kernel events: '%s' exceeds the maximal allowed length of %zu bytes", - kevent->event->name, - sizeof(event.name)); - ret = -LTTNG_ERR_UNK; + if (!tmp_event) { + ret_code = LTTNG_ERR_NOMEM; goto end; } - event.enabled = kevent->enabled; - event.filter = (unsigned char) !!kevent->filter_expression; + if (lttng_strncpy(tmp_event->name, event->event->name, LTTNG_SYMBOL_NAME_LEN)) { + lttng_event_destroy(tmp_event); + ret_code = LTTNG_ERR_FATAL; + goto end; - switch (kevent->event->instrumentation) { + } + + tmp_event->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; + tmp_event->enabled = event->enabled; + tmp_event->filter = (unsigned char) !!event->filter_expression; + + switch (event->event->instrumentation) { case LTTNG_KERNEL_ABI_TRACEPOINT: - event.type = LTTNG_EVENT_TRACEPOINT; + tmp_event->type = LTTNG_EVENT_TRACEPOINT; break; case LTTNG_KERNEL_ABI_KRETPROBE: - event.type = LTTNG_EVENT_FUNCTION; - memcpy(&event.attr.probe, &kevent->event->u.kprobe, + tmp_event->type = LTTNG_EVENT_FUNCTION; + memcpy(&tmp_event->attr.probe, &event->event->u.kprobe, sizeof(struct lttng_kernel_abi_kprobe)); break; case LTTNG_KERNEL_ABI_KPROBE: - event.type = LTTNG_EVENT_PROBE; - memcpy(&event.attr.probe, &kevent->event->u.kprobe, + tmp_event->type = LTTNG_EVENT_PROBE; + memcpy(&tmp_event->attr.probe, &event->event->u.kprobe, sizeof(struct lttng_kernel_abi_kprobe)); break; case LTTNG_KERNEL_ABI_UPROBE: - event.type = LTTNG_EVENT_USERSPACE_PROBE; + tmp_event->type = LTTNG_EVENT_USERSPACE_PROBE; break; case LTTNG_KERNEL_ABI_FUNCTION: - event.type = LTTNG_EVENT_FUNCTION; - memcpy(&event.attr.ftrace, &kevent->event->u.ftrace, + tmp_event->type = LTTNG_EVENT_FUNCTION; + memcpy(&(tmp_event->attr.ftrace), &event->event->u.ftrace, sizeof(struct lttng_kernel_abi_function)); break; case LTTNG_KERNEL_ABI_NOOP: - event.type = LTTNG_EVENT_NOOP; + tmp_event->type = LTTNG_EVENT_NOOP; break; case LTTNG_KERNEL_ABI_SYSCALL: - event.type = LTTNG_EVENT_SYSCALL; + tmp_event->type = LTTNG_EVENT_SYSCALL; break; case LTTNG_KERNEL_ABI_ALL: /* fall-through. */ @@ -607,30 +581,40 @@ static int list_lttng_kernel_events(char *channel_name, break; } - ret = lttng_dynamic_buffer_append( - &payload->buffer, &event, sizeof(event)); - if (ret) { - ERR("Failed to append event to payload"); - ret = -LTTNG_ERR_NOMEM; - goto end; + if (event->userspace_probe_location) { + struct lttng_userspace_probe_location *location_copy = + lttng_userspace_probe_location_copy( + event->userspace_probe_location); + + if (!location_copy) { + lttng_event_destroy(tmp_event); + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + + ret = lttng_event_set_userspace_probe_location( + tmp_event, location_copy); + if (ret) { + lttng_event_destroy(tmp_event); + lttng_userspace_probe_location_destroy( + location_copy); + ret_code = LTTNG_ERR_INVALID; + goto end; + } } - } - cds_list_for_each_entry(kevent, &kchan->events_list.head , list) { - /* Append extended info. */ - ret = append_extended_info(kevent->filter_expression, NULL, - kevent->userspace_probe_location, payload); + ret = lttng_event_serialize(tmp_event, 0, NULL, + event->filter_expression, 0, NULL, reply_payload); + lttng_event_destroy(tmp_event); if (ret) { - DBG("Error appending extended info message"); - ret = -LTTNG_ERR_FATAL; - goto error; + ret_code = LTTNG_ERR_FATAL; + goto end; } } + ret_code = LTTNG_OK; end: - return nb_event; -error: - return ret; + return ret_code; } /* @@ -942,7 +926,6 @@ relayd_comm_error: * Returns LTTNG_OK, or an LTTng error code on failure. */ static enum lttng_error_code send_consumer_relayd_sockets( - enum lttng_domain_type domain, unsigned int session_id, struct consumer_output *consumer, struct consumer_socket *sock, const char *session_name, const char *hostname, const char *base_path, int session_live_timer, @@ -1023,7 +1006,7 @@ int cmd_setup_relayd(struct ltt_session *session) cds_lfht_for_each_entry(usess->consumer->socks->ht, &iter.iter, socket, node.node) { pthread_mutex_lock(socket->lock); - ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_UST, session->id, + ret = send_consumer_relayd_sockets(session->id, usess->consumer, socket, session->name, session->hostname, session->base_path, @@ -1051,7 +1034,7 @@ int cmd_setup_relayd(struct ltt_session *session) cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter, socket, node.node) { pthread_mutex_lock(socket->lock); - ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_KERNEL, session->id, + ret = send_consumer_relayd_sockets(session->id, ksess->consumer, socket, session->name, session->hostname, session->base_path, @@ -1299,12 +1282,13 @@ end: return ret; } -static int cmd_enable_channel_internal(struct ltt_session *session, +static enum lttng_error_code cmd_enable_channel_internal( + struct ltt_session *session, const struct lttng_domain *domain, const struct lttng_channel *_attr, int wpipe) { - int ret; + enum lttng_error_code ret_code; struct ltt_ust_session *usess = session->ust_session; struct lttng_ht *chan_ht; size_t len; @@ -1316,7 +1300,7 @@ static int cmd_enable_channel_internal(struct ltt_session *session, attr = lttng_channel_copy(_attr); if (!attr) { - ret = -LTTNG_ERR_NOMEM; + ret_code = LTTNG_ERR_NOMEM; goto end; } @@ -1325,7 +1309,7 @@ static int cmd_enable_channel_internal(struct ltt_session *session, /* Validate channel name */ if (attr->name[0] == '.' || memchr(attr->name, '/', len) != NULL) { - ret = LTTNG_ERR_INVALID_CHANNEL_NAME; + ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME; goto end; } @@ -1364,12 +1348,12 @@ static int cmd_enable_channel_internal(struct ltt_session *session, case LTTNG_DOMAIN_PYTHON: if (!agent_tracing_is_enabled()) { DBG("Attempted to enable a channel in an agent domain but the agent thread is not running"); - ret = LTTNG_ERR_AGENT_TRACING_DISABLED; + ret_code = LTTNG_ERR_AGENT_TRACING_DISABLED; goto error; } break; default: - ret = LTTNG_ERR_UNKNOWN_DOMAIN; + ret_code = LTTNG_ERR_UNKNOWN_DOMAIN; goto error; } @@ -1386,7 +1370,7 @@ static int cmd_enable_channel_internal(struct ltt_session *session, * some point in time before. The tracer does not allow it. */ if (session->has_been_started) { - ret = LTTNG_ERR_TRACE_ALREADY_STARTED; + ret_code = LTTNG_ERR_TRACE_ALREADY_STARTED; goto error; } @@ -1395,16 +1379,16 @@ static int cmd_enable_channel_internal(struct ltt_session *session, /* Enforce mmap output for snapshot sessions. */ attr->attr.output = LTTNG_EVENT_MMAP; } - ret = channel_kernel_create( + ret_code = channel_kernel_create( session->kernel_session, attr, wpipe); if (attr->name[0] != '\0') { session->kernel_session->has_non_default_channel = 1; } } else { - ret = channel_kernel_enable(session->kernel_session, kchan); + ret_code = channel_kernel_enable(session->kernel_session, kchan); } - if (ret != LTTNG_OK) { + if (ret_code != LTTNG_OK) { goto error; } @@ -1429,19 +1413,19 @@ static int cmd_enable_channel_internal(struct ltt_session *session, if (domain->type == LTTNG_DOMAIN_JUL) { if (strncmp(attr->name, DEFAULT_JUL_CHANNEL_NAME, LTTNG_SYMBOL_NAME_LEN)) { - ret = LTTNG_ERR_INVALID_CHANNEL_NAME; + ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME; goto error; } } else if (domain->type == LTTNG_DOMAIN_LOG4J) { if (strncmp(attr->name, DEFAULT_LOG4J_CHANNEL_NAME, LTTNG_SYMBOL_NAME_LEN)) { - ret = LTTNG_ERR_INVALID_CHANNEL_NAME; + ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME; goto error; } } else if (domain->type == LTTNG_DOMAIN_PYTHON) { if (strncmp(attr->name, DEFAULT_PYTHON_CHANNEL_NAME, LTTNG_SYMBOL_NAME_LEN)) { - ret = LTTNG_ERR_INVALID_CHANNEL_NAME; + ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME; goto error; } } @@ -1455,32 +1439,32 @@ static int cmd_enable_channel_internal(struct ltt_session *session, * some point in time before. The tracer does not allow it. */ if (session->has_been_started) { - ret = LTTNG_ERR_TRACE_ALREADY_STARTED; + ret_code = LTTNG_ERR_TRACE_ALREADY_STARTED; goto error; } - ret = channel_ust_create(usess, attr, domain->buf_type); + ret_code = channel_ust_create(usess, attr, domain->buf_type); if (attr->name[0] != '\0') { usess->has_non_default_channel = 1; } } else { - ret = channel_ust_enable(usess, uchan); + ret_code = channel_ust_enable(usess, uchan); } break; } default: - ret = LTTNG_ERR_UNKNOWN_DOMAIN; + ret_code = LTTNG_ERR_UNKNOWN_DOMAIN; goto error; } - if (ret == LTTNG_OK && attr->attr.output != LTTNG_EVENT_MMAP) { + if (ret_code == LTTNG_OK && attr->attr.output != LTTNG_EVENT_MMAP) { session->has_non_mmap_channel = true; } error: rcu_read_unlock(); end: lttng_channel_destroy(attr); - return ret; + return ret_code; } enum lttng_error_code cmd_process_attr_tracker_get_tracking_policy( @@ -1691,15 +1675,33 @@ end: /* * Command LTTNG_DISABLE_EVENT processed by the client thread. */ -int cmd_disable_event(struct ltt_session *session, - enum lttng_domain_type domain, const char *channel_name, - const struct lttng_event *event) +int cmd_disable_event(struct command_ctx *cmd_ctx, + struct lttng_event *event, + char *filter_expression, + struct lttng_bytecode *bytecode, + struct lttng_event_exclusion *exclusion) { int ret; const char *event_name; + const struct ltt_session *session = cmd_ctx->session; + const char *channel_name = cmd_ctx->lsm.u.disable.channel_name; + const enum lttng_domain_type domain = cmd_ctx->lsm.domain.type; DBG("Disable event command for event \'%s\'", event->name); + /* + * Filter and exclusions are simply not handled by the + * disable event command at this time. + * + * FIXME + */ + (void) filter_expression; + (void) exclusion; + + /* Ignore the presence of filter or exclusion for the event */ + event->filter = 0; + event->exclusion = 0; + event_name = event->name; /* Error out on unhandled search criteria */ @@ -1862,33 +1864,33 @@ int cmd_disable_event(struct ltt_session *session, error_unlock: rcu_read_unlock(); error: + free(exclusion); + free(bytecode); + free(filter_expression); return ret; } /* * Command LTTNG_ADD_CONTEXT processed by the client thread. */ -int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain, - char *channel_name, const struct lttng_event_context *ctx, int kwpipe) +int cmd_add_context(struct command_ctx *cmd_ctx, + const struct lttng_event_context *event_context, int kwpipe) { int ret, chan_kern_created = 0, chan_ust_created = 0; - char *app_ctx_provider_name = NULL, *app_ctx_name = NULL; + const enum lttng_domain_type domain = cmd_ctx->lsm.domain.type; + const struct ltt_session *session = cmd_ctx->session; + const char *channel_name = cmd_ctx->lsm.u.context.channel_name; /* * Don't try to add a context if the session has been started at * some point in time before. The tracer does not allow it and would * result in a corrupted trace. */ - if (session->has_been_started) { + if (cmd_ctx->session->has_been_started) { ret = LTTNG_ERR_TRACE_ALREADY_STARTED; goto end; } - if (ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) { - app_ctx_provider_name = ctx->u.app_ctx.provider_name; - app_ctx_name = ctx->u.app_ctx.ctx_name; - } - switch (domain) { case LTTNG_DOMAIN_KERNEL: LTTNG_ASSERT(session->kernel_session); @@ -1902,7 +1904,8 @@ int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain, chan_kern_created = 1; } /* Add kernel context to kernel tracer */ - ret = context_kernel_add(session->kernel_session, ctx, channel_name); + ret = context_kernel_add(session->kernel_session, + event_context, channel_name); if (ret != LTTNG_OK) { goto error; } @@ -1928,8 +1931,8 @@ int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain, ret = LTTNG_ERR_UST_CHAN_NOT_FOUND; goto error; } - /* break is _not_ missing here. */ } + /* fall through */ case LTTNG_DOMAIN_UST: { struct ltt_ust_session *usess = session->ust_session; @@ -1956,11 +1959,8 @@ int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain, chan_ust_created = 1; } - ret = context_ust_add(usess, domain, ctx, channel_name); - free(app_ctx_provider_name); - free(app_ctx_name); - app_ctx_name = NULL; - app_ctx_provider_name = NULL; + ret = context_ust_add(usess, domain, event_context, + channel_name); if (ret != LTTNG_OK) { goto error; } @@ -1997,8 +1997,6 @@ error: trace_ust_destroy_channel(uchan); } end: - free(app_ctx_provider_name); - free(app_ctx_name); return ret; } @@ -2439,16 +2437,35 @@ error: * Command LTTNG_ENABLE_EVENT processed by the client thread. * We own filter, exclusion, and filter_expression. */ -int cmd_enable_event(struct ltt_session *session, - const struct lttng_domain *domain, - char *channel_name, struct lttng_event *event, +int cmd_enable_event(struct command_ctx *cmd_ctx, + struct lttng_event *event, char *filter_expression, - struct lttng_bytecode *filter, struct lttng_event_exclusion *exclusion, + struct lttng_bytecode *bytecode, int wpipe) { - return _cmd_enable_event(session, domain, channel_name, event, - filter_expression, filter, exclusion, wpipe, false); + int ret; + /* + * Copied to ensure proper alignment since 'lsm' is a packed structure. + */ + const lttng_domain command_domain = cmd_ctx->lsm.domain; + + /* + * The ownership of the following parameters is transferred to + * _cmd_enable_event: + * + * - filter_expression, + * - bytecode, + * - exclusion + */ + ret = _cmd_enable_event(cmd_ctx->session, + &command_domain, + cmd_ctx->lsm.u.enable.channel_name, event, + filter_expression, bytecode, exclusion, wpipe, false); + filter_expression = NULL; + bytecode = NULL; + exclusion = NULL; + return ret; } /* @@ -2471,81 +2488,204 @@ static int cmd_enable_event_internal(struct ltt_session *session, /* * Command LTTNG_LIST_TRACEPOINTS processed by the client thread. */ -ssize_t cmd_list_tracepoints(enum lttng_domain_type domain, - struct lttng_event **events) +enum lttng_error_code cmd_list_tracepoints(enum lttng_domain_type domain, + struct lttng_payload *reply_payload) { + enum lttng_error_code ret_code; int ret; - ssize_t nb_events = 0; + ssize_t i, nb_events = 0; + struct lttng_event *events = NULL; + struct lttcomm_list_command_header reply_command_header = {}; + size_t reply_command_header_offset; + + assert(reply_payload); + + /* Reserve space for command reply header. */ + reply_command_header_offset = reply_payload->buffer.size; + ret = lttng_dynamic_buffer_set_size(&reply_payload->buffer, + reply_command_header_offset + + sizeof(struct lttcomm_list_command_header)); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto error; + } switch (domain) { case LTTNG_DOMAIN_KERNEL: - nb_events = kernel_list_events(events); + nb_events = kernel_list_events(&events); if (nb_events < 0) { - ret = LTTNG_ERR_KERN_LIST_FAIL; + ret_code = LTTNG_ERR_KERN_LIST_FAIL; goto error; } break; case LTTNG_DOMAIN_UST: - nb_events = ust_app_list_events(events); + nb_events = ust_app_list_events(&events); if (nb_events < 0) { - ret = LTTNG_ERR_UST_LIST_FAIL; + ret_code = LTTNG_ERR_UST_LIST_FAIL; goto error; } break; case LTTNG_DOMAIN_LOG4J: case LTTNG_DOMAIN_JUL: case LTTNG_DOMAIN_PYTHON: - nb_events = agent_list_events(events, domain); + nb_events = agent_list_events(&events, domain); if (nb_events < 0) { - ret = LTTNG_ERR_UST_LIST_FAIL; + ret_code = LTTNG_ERR_UST_LIST_FAIL; goto error; } break; default: - ret = LTTNG_ERR_UND; + ret_code = LTTNG_ERR_UND; goto error; } - return nb_events; + for (i = 0; i < nb_events; i++) { + ret = lttng_event_serialize(&events[i], 0, NULL, NULL, 0, NULL, + reply_payload); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto error; + } + } + if (nb_events > UINT32_MAX) { + ERR("Tracepoint count would overflow the tracepoint listing command's reply"); + ret_code = LTTNG_ERR_OVERFLOW; + goto error; + } + + /* Update command reply header. */ + reply_command_header.count = (uint32_t) nb_events; + memcpy(reply_payload->buffer.data + reply_command_header_offset, &reply_command_header, + sizeof(reply_command_header)); + + ret_code = LTTNG_OK; error: - /* Return negative value to differentiate return code */ - return -ret; + free(events); + return ret_code; } /* * Command LTTNG_LIST_TRACEPOINT_FIELDS processed by the client thread. */ -ssize_t cmd_list_tracepoint_fields(enum lttng_domain_type domain, - struct lttng_event_field **fields) +enum lttng_error_code cmd_list_tracepoint_fields(enum lttng_domain_type domain, + struct lttng_payload *reply) { + enum lttng_error_code ret_code; int ret; - ssize_t nb_fields = 0; + unsigned int i, nb_fields; + struct lttng_event_field *fields = NULL; + struct lttcomm_list_command_header reply_command_header = {}; + size_t reply_command_header_offset; + + assert(reply); + + /* Reserve space for command reply header. */ + reply_command_header_offset = reply->buffer.size; + ret = lttng_dynamic_buffer_set_size(&reply->buffer, + reply_command_header_offset + + sizeof(struct lttcomm_list_command_header)); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto error; + } switch (domain) { case LTTNG_DOMAIN_UST: - nb_fields = ust_app_list_event_fields(fields); - if (nb_fields < 0) { - ret = LTTNG_ERR_UST_LIST_FAIL; + ret = ust_app_list_event_fields(&fields); + if (ret < 0) { + ret_code = LTTNG_ERR_UST_LIST_FAIL; goto error; } + break; case LTTNG_DOMAIN_KERNEL: default: /* fall-through */ - ret = LTTNG_ERR_UND; + ret_code = LTTNG_ERR_UND; goto error; } - return nb_fields; + nb_fields = ret; + + for (i = 0; i < nb_fields; i++) { + ret = lttng_event_field_serialize(&fields[i], reply); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto error; + } + } + + if (nb_fields > UINT32_MAX) { + ERR("Tracepoint field count would overflow the tracepoint field listing command's reply"); + ret_code = LTTNG_ERR_OVERFLOW; + goto error; + } + + /* Update command reply header. */ + reply_command_header.count = (uint32_t) nb_fields; + + memcpy(reply->buffer.data + reply_command_header_offset, &reply_command_header, + sizeof(reply_command_header)); + + ret_code = LTTNG_OK; error: - /* Return negative value to differentiate return code */ - return -ret; + free(fields); + return ret_code; } -ssize_t cmd_list_syscalls(struct lttng_event **events) +enum lttng_error_code cmd_list_syscalls( + struct lttng_payload *reply_payload) { - return syscall_table_list(events); + enum lttng_error_code ret_code; + ssize_t nb_events, i; + int ret; + struct lttng_event *events = NULL; + struct lttcomm_list_command_header reply_command_header = {}; + size_t reply_command_header_offset; + + assert(reply_payload); + + /* Reserve space for command reply header. */ + reply_command_header_offset = reply_payload->buffer.size; + ret = lttng_dynamic_buffer_set_size(&reply_payload->buffer, + reply_command_header_offset + + sizeof(struct lttcomm_list_command_header)); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + + nb_events = syscall_table_list(&events); + if (nb_events < 0) { + ret_code = (enum lttng_error_code) -nb_events; + goto end; + } + + for (i = 0; i < nb_events; i++) { + ret = lttng_event_serialize(&events[i], 0, NULL, NULL, 0, NULL, + reply_payload); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + } + + if (nb_events > UINT32_MAX) { + ERR("Syscall count would overflow the syscall listing command's reply"); + ret_code = LTTNG_ERR_OVERFLOW; + goto end; + } + + /* Update command reply header. */ + reply_command_header.count = (uint32_t) nb_events; + memcpy(reply_payload->buffer.data + reply_command_header_offset, &reply_command_header, + sizeof(reply_command_header)); + + ret_code = LTTNG_OK; +end: + free(events); + return ret_code; } /* @@ -2687,7 +2827,7 @@ int cmd_start_trace(struct ltt_session *session) */ session->rotated_after_last_stop = false; - if (session->rotate_timer_period) { + if (session->rotate_timer_period && !session->rotation_schedule_timer_enabled) { int int_ret = timer_session_rotation_schedule_timer_start( session, session->rotate_timer_period); @@ -3157,6 +3297,7 @@ void cmd_destroy_session_reply(const struct ltt_session *session, .cmd_header_size = sizeof(struct lttcomm_session_destroy_command_header), .data_size = 0, + .fd_count = 0, }; size_t payload_size_before_location; @@ -3634,8 +3775,8 @@ enum lttng_error_code cmd_list_channels(enum lttng_domain_type domain, channel = trace_ust_channel_to_lttng_channel(uchan); if (!channel) { - ret = LTTNG_ERR_NOMEM; - break; + ret_code = LTTNG_ERR_NOMEM; + goto end; } extended = (struct lttng_channel_extended *) @@ -3646,7 +3787,7 @@ enum lttng_error_code cmd_list_channels(enum lttng_domain_type domain, if (ret < 0) { lttng_channel_destroy(channel); ret_code = LTTNG_ERR_UNK; - break; + goto end; } extended->discarded_events = discarded_events; @@ -3657,11 +3798,12 @@ enum lttng_error_code cmd_list_channels(enum lttng_domain_type domain, if (ret) { ERR("Failed to serialize lttng_channel: channel name = '%s'", channel->name); + lttng_channel_destroy(channel); ret_code = LTTNG_ERR_UNK; - ret = -1; - break; + goto end; } + lttng_channel_destroy(channel); i++; } rcu_read_unlock(); @@ -3690,36 +3832,45 @@ end: /* * Command LTTNG_LIST_EVENTS processed by the client thread. */ -ssize_t cmd_list_events(enum lttng_domain_type domain, - struct ltt_session *session, char *channel_name, - struct lttng_payload *payload) +enum lttng_error_code cmd_list_events(enum lttng_domain_type domain, + struct ltt_session *session, + char *channel_name, + struct lttng_payload *reply_payload) { - int ret = 0; - ssize_t nb_events = 0; - struct lttcomm_event_command_header cmd_header = {}; - const size_t cmd_header_offset = payload->buffer.size; + int buffer_resize_ret; + enum lttng_error_code ret_code = LTTNG_OK; + struct lttcomm_list_command_header reply_command_header = {}; + size_t reply_command_header_offset; + unsigned int nb_events = 0; - ret = lttng_dynamic_buffer_append( - &payload->buffer, &cmd_header, sizeof(cmd_header)); - if (ret) { - ret = LTTNG_ERR_NOMEM; - goto error; + assert(reply_payload); + + /* Reserve space for command reply header. */ + reply_command_header_offset = reply_payload->buffer.size; + buffer_resize_ret = lttng_dynamic_buffer_set_size(&reply_payload->buffer, + reply_command_header_offset + + sizeof(struct lttcomm_list_command_header)); + if (buffer_resize_ret) { + ret_code = LTTNG_ERR_NOMEM; + goto end; } switch (domain) { case LTTNG_DOMAIN_KERNEL: if (session->kernel_session != NULL) { - nb_events = list_lttng_kernel_events(channel_name, - session->kernel_session, payload); + ret_code = list_lttng_kernel_events(channel_name, + session->kernel_session, reply_payload, &nb_events); } + break; case LTTNG_DOMAIN_UST: { if (session->ust_session != NULL) { - nb_events = list_lttng_ust_global_events(channel_name, + ret_code = list_lttng_ust_global_events(channel_name, &session->ust_session->domain_global, - payload); + reply_payload, &nb_events); } + break; } case LTTNG_DOMAIN_LOG4J: @@ -3733,27 +3884,32 @@ ssize_t cmd_list_events(enum lttng_domain_type domain, cds_lfht_for_each_entry(session->ust_session->agents->ht, &iter.iter, agt, node.node) { if (agt->domain == domain) { - nb_events = list_lttng_agent_events( - agt, payload); + ret_code = list_lttng_agent_events( + agt, reply_payload, &nb_events); break; } } + rcu_read_unlock(); } break; default: - ret = LTTNG_ERR_UND; - goto error; + ret_code = LTTNG_ERR_UND; + break; } - ((struct lttcomm_event_command_header *) (payload->buffer.data + - cmd_header_offset))->nb_events = (uint32_t) nb_events; + if (nb_events > UINT32_MAX) { + ret_code = LTTNG_ERR_OVERFLOW; + goto end; + } - return nb_events; + /* Update command reply header. */ + reply_command_header.count = (uint32_t) nb_events; + memcpy(reply_payload->buffer.data + reply_command_header_offset, &reply_command_header, + sizeof(reply_command_header)); -error: - /* Return negative value to differentiate return code */ - return -ret; +end: + return ret_code; } /* @@ -4892,7 +5048,7 @@ static enum lttng_error_code set_relayd_for_snapshot( cds_lfht_for_each_entry(output->socks->ht, &iter.iter, socket, node.node) { pthread_mutex_lock(socket->lock); - status = send_consumer_relayd_sockets(LTTNG_DOMAIN_NONE, session->id, + status = send_consumer_relayd_sockets(session->id, output, socket, session->name, session->hostname, base_path, @@ -4921,7 +5077,7 @@ static enum lttng_error_code record_kernel_snapshot( struct ltt_kernel_session *ksess, const struct consumer_output *output, const struct ltt_session *session, - int wait, uint64_t nb_packets_per_stream) + uint64_t nb_packets_per_stream) { enum lttng_error_code status; @@ -4930,7 +5086,7 @@ static enum lttng_error_code record_kernel_snapshot( LTTNG_ASSERT(session); status = kernel_snapshot_record( - ksess, output, wait, nb_packets_per_stream); + ksess, output, nb_packets_per_stream); return status; } @@ -4942,7 +5098,7 @@ static enum lttng_error_code record_kernel_snapshot( static enum lttng_error_code record_ust_snapshot(struct ltt_ust_session *usess, const struct consumer_output *output, const struct ltt_session *session, - int wait, uint64_t nb_packets_per_stream) + uint64_t nb_packets_per_stream) { enum lttng_error_code status; @@ -4951,7 +5107,7 @@ static enum lttng_error_code record_ust_snapshot(struct ltt_ust_session *usess, LTTNG_ASSERT(session); status = ust_app_snapshot_record( - usess, output, wait, nb_packets_per_stream); + usess, output, nb_packets_per_stream); return status; } @@ -5045,7 +5201,7 @@ int64_t get_session_nb_packets_per_stream(const struct ltt_session *session, static enum lttng_error_code snapshot_record(struct ltt_session *session, - const struct snapshot_output *snapshot_output, int wait) + const struct snapshot_output *snapshot_output) { int64_t nb_packets_per_stream; char snapshot_chunk_name[LTTNG_NAME_MAX]; @@ -5165,7 +5321,7 @@ enum lttng_error_code snapshot_record(struct ltt_session *session, if (session->kernel_session) { ret_code = record_kernel_snapshot(session->kernel_session, snapshot_kernel_consumer_output, session, - wait, nb_packets_per_stream); + nb_packets_per_stream); if (ret_code != LTTNG_OK) { goto error_close_trace_chunk; } @@ -5174,7 +5330,7 @@ enum lttng_error_code snapshot_record(struct ltt_session *session, if (session->ust_session) { ret_code = record_ust_snapshot(session->ust_session, snapshot_ust_consumer_output, session, - wait, nb_packets_per_stream); + nb_packets_per_stream); if (ret_code != LTTNG_OK) { goto error_close_trace_chunk; } @@ -5222,7 +5378,8 @@ error: * Return LTTNG_OK on success or else a LTTNG_ERR code. */ int cmd_snapshot_record(struct ltt_session *session, - const struct lttng_snapshot_output *output, int wait) + const struct lttng_snapshot_output *output, + int wait __attribute__((unused))) { enum lttng_error_code cmd_ret = LTTNG_OK; int ret; @@ -5284,7 +5441,7 @@ int cmd_snapshot_record(struct ltt_session *session, /* Use the global datetime */ memcpy(tmp_output->datetime, datetime, sizeof(datetime)); - cmd_ret = snapshot_record(session, tmp_output, wait); + cmd_ret = snapshot_record(session, tmp_output); if (cmd_ret != LTTNG_OK) { goto error; } @@ -5324,7 +5481,7 @@ int cmd_snapshot_record(struct ltt_session *session, } } - cmd_ret = snapshot_record(session, &output_copy, wait); + cmd_ret = snapshot_record(session, &output_copy); if (cmd_ret != LTTNG_OK) { rcu_read_unlock(); goto error;