X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-app.cpp;h=16848191d6f6d8f8b2bde23e207d3a3f47b8824c;hb=97f630d42cd12a475293af66e75a71ab7b490633;hp=66d363c4b064ea003e8577a5e504aaf5b126d6b8;hpb=aeeb48c6a7dd4bcc092b3105439489fc393f6425;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/ust-app.cpp b/src/bin/lttng-sessiond/ust-app.cpp index 66d363c4b..16848191d 100644 --- a/src/bin/lttng-sessiond/ust-app.cpp +++ b/src/bin/lttng-sessiond/ust-app.cpp @@ -7,10 +7,48 @@ */ #define _LGPL_SOURCE + +#include "buffer-registry.hpp" +#include "condition-internal.hpp" +#include "event-notifier-error-accounting.hpp" +#include "event.hpp" +#include "fd-limit.hpp" +#include "field.hpp" +#include "health-sessiond.hpp" +#include "lttng-sessiond.hpp" +#include "lttng-ust-ctl.hpp" +#include "lttng-ust-error.hpp" +#include "notification-thread-commands.hpp" +#include "rotate.hpp" +#include "session.hpp" +#include "ust-app.hpp" +#include "ust-consumer.hpp" +#include "ust-field-convert.hpp" +#include "utils.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + #include #include #include #include +#include #include #include #include @@ -19,37 +57,10 @@ #include #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "buffer-registry.hpp" -#include "condition-internal.hpp" -#include "fd-limit.hpp" -#include "health-sessiond.hpp" -#include "ust-app.hpp" -#include "ust-consumer.hpp" -#include "lttng-ust-ctl.hpp" -#include "lttng-ust-error.hpp" -#include "utils.hpp" -#include "session.hpp" -#include "lttng-sessiond.hpp" -#include "notification-thread-commands.hpp" -#include "rotate.hpp" -#include "event.hpp" -#include "event-notifier-error-accounting.hpp" -#include "ust-field-utils.hpp" +namespace lsu = lttng::sessiond::ust; +namespace lst = lttng::sessiond::trace; struct lttng_ht *ust_app_ht; struct lttng_ht *ust_app_ht_by_sock; @@ -66,6 +77,63 @@ static pthread_mutex_t next_channel_key_lock = PTHREAD_MUTEX_INITIALIZER; static uint64_t _next_session_id; static pthread_mutex_t next_session_id_lock = PTHREAD_MUTEX_INITIALIZER; +namespace { + +/* + * Return the session registry according to the buffer type of the given + * session. + * + * A registry per UID object MUST exists before calling this function or else + * it LTTNG_ASSERT() if not found. RCU read side lock must be acquired. + */ +static lsu::registry_session *get_session_registry( + const struct ust_app_session *ua_sess) +{ + lsu::registry_session *registry = NULL; + + LTTNG_ASSERT(ua_sess); + + switch (ua_sess->buffer_type) { + case LTTNG_BUFFER_PER_PID: + { + struct buffer_reg_pid *reg_pid = buffer_reg_pid_find(ua_sess->id); + if (!reg_pid) { + goto error; + } + registry = reg_pid->registry->reg.ust; + break; + } + case LTTNG_BUFFER_PER_UID: + { + struct buffer_reg_uid *reg_uid = buffer_reg_uid_find( + ua_sess->tracing_id, ua_sess->bits_per_long, + lttng_credentials_get_uid(&ua_sess->real_credentials)); + if (!reg_uid) { + goto error; + } + registry = reg_uid->registry->reg.ust; + break; + } + default: + abort(); + }; + +error: + return registry; +} + +lsu::registry_session::locked_ptr +get_locked_session_registry(const struct ust_app_session *ua_sess) +{ + auto session = get_session_registry(ua_sess); + if (session) { + pthread_mutex_lock(&session->_lock); + } + + return lsu::registry_session::locked_ptr{session}; +} +} /* namespace */ + /* * Return the incremented value of next_channel_key. */ @@ -233,49 +301,6 @@ static void close_notify_sock_rcu(struct rcu_head *head) free(obj); } -/* - * Return the session registry according to the buffer type of the given - * session. - * - * A registry per UID object MUST exists before calling this function or else - * it LTTNG_ASSERT() if not found. RCU read side lock must be acquired. - */ -static ust_registry_session *get_session_registry( - struct ust_app_session *ua_sess) -{ - ust_registry_session *registry = NULL; - - LTTNG_ASSERT(ua_sess); - - switch (ua_sess->buffer_type) { - case LTTNG_BUFFER_PER_PID: - { - struct buffer_reg_pid *reg_pid = buffer_reg_pid_find(ua_sess->id); - if (!reg_pid) { - goto error; - } - registry = reg_pid->registry->reg.ust; - break; - } - case LTTNG_BUFFER_PER_UID: - { - struct buffer_reg_uid *reg_uid = buffer_reg_uid_find( - ua_sess->tracing_id, ua_sess->bits_per_long, - lttng_credentials_get_uid(&ua_sess->real_credentials)); - if (!reg_uid) { - goto error; - } - registry = reg_uid->registry->reg.ust; - break; - } - default: - abort(); - }; - -error: - return registry; -} - /* * Delete ust context safely. RCU read lock must be held before calling * this function. @@ -534,16 +559,16 @@ end: * * The session list lock must be held by the caller. */ -static -void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, - struct ust_app *app) +static void delete_ust_app_channel(int sock, + struct ust_app_channel *ua_chan, + struct ust_app *app, + const lsu::registry_session::locked_ptr& locked_registry) { int ret; struct lttng_ht_iter iter; struct ust_app_event *ua_event; struct ust_app_ctx *ua_ctx; struct ust_app_stream *stream, *stmp; - ust_registry_session *registry; LTTNG_ASSERT(ua_chan); ASSERT_RCU_READ_LOCKED(); @@ -574,11 +599,14 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, if (ua_chan->session->buffer_type == LTTNG_BUFFER_PER_PID) { /* Wipe and free registry from session registry. */ - registry = get_session_registry(ua_chan->session); - if (registry) { - ust_registry_channel_del_free(registry, ua_chan->key, - sock >= 0); + if (locked_registry) { + try { + locked_registry->remove_channel(ua_chan->key, sock >= 0); + } catch (const std::exception &ex) { + DBG("Could not find channel for removal: %s", ex.what()); + } } + /* * A negative socket can be used by the caller when * cleaning-up a ua_chan in an error path. Skip the @@ -657,8 +685,9 @@ int ust_app_release_object(struct ust_app *app, struct lttng_ust_abi_object_data * but it can be caused by recoverable errors (e.g. the application has * terminated concurrently). */ -ssize_t ust_app_push_metadata(ust_registry_session *registry, - struct consumer_socket *socket, int send_zero_data) +ssize_t ust_app_push_metadata(const lsu::registry_session::locked_ptr& locked_registry, + struct consumer_socket *socket, + int send_zero_data) { int ret; char *metadata_str = NULL; @@ -666,11 +695,11 @@ ssize_t ust_app_push_metadata(ust_registry_session *registry, ssize_t ret_val; uint64_t metadata_key, metadata_version; - LTTNG_ASSERT(registry); + LTTNG_ASSERT(locked_registry); LTTNG_ASSERT(socket); ASSERT_RCU_READ_LOCKED(); - metadata_key = registry->_metadata_key; + metadata_key = locked_registry->_metadata_key; /* * Means that no metadata was assigned to the session. This can @@ -680,13 +709,13 @@ ssize_t ust_app_push_metadata(ust_registry_session *registry, return 0; } - offset = registry->_metadata_len_sent; - len = registry->_metadata_len - registry->_metadata_len_sent; - new_metadata_len_sent = registry->_metadata_len; - metadata_version = registry->_metadata_version; + offset = locked_registry->_metadata_len_sent; + len = locked_registry->_metadata_len - locked_registry->_metadata_len_sent; + new_metadata_len_sent = locked_registry->_metadata_len; + metadata_version = locked_registry->_metadata_version; if (len == 0) { DBG3("No metadata to push for metadata key %" PRIu64, - registry->_metadata_key); + locked_registry->_metadata_key); ret_val = len; if (send_zero_data) { DBG("No metadata to push"); @@ -703,10 +732,10 @@ ssize_t ust_app_push_metadata(ust_registry_session *registry, goto error; } /* Copy what we haven't sent out. */ - memcpy(metadata_str, registry->_metadata + offset, len); + memcpy(metadata_str, locked_registry->_metadata + offset, len); push_data: - pthread_mutex_unlock(®istry->_lock); + pthread_mutex_unlock(&locked_registry->_lock); /* * We need to unlock the registry while we push metadata to * break a circular dependency between the consumerd metadata @@ -721,7 +750,7 @@ push_data: */ ret = consumer_push_metadata(socket, metadata_key, metadata_str, len, offset, metadata_version); - pthread_mutex_lock(®istry->_lock); + pthread_mutex_lock(&locked_registry->_lock); if (ret < 0) { /* * There is an acceptable race here between the registry @@ -758,8 +787,8 @@ push_data: * largest metadata_len_sent value of the concurrent * send. */ - registry->_metadata_len_sent = - std::max(registry->_metadata_len_sent, + locked_registry->_metadata_len_sent = + std::max(locked_registry->_metadata_len_sent, new_metadata_len_sent); } free(metadata_str); @@ -775,7 +804,7 @@ error: * the metadata cache has been destroyed on the * consumer. */ - registry->_metadata_closed = true; + locked_registry->_metadata_closed = true; } error_push: free(metadata_str); @@ -796,41 +825,38 @@ error_push: * but it can be caused by recoverable errors (e.g. the application has * terminated concurrently). */ -static int push_metadata(ust_registry_session *registry, +static int push_metadata(const lsu::registry_session::locked_ptr& locked_registry, struct consumer_output *consumer) { int ret_val; ssize_t ret; struct consumer_socket *socket; - LTTNG_ASSERT(registry); + LTTNG_ASSERT(locked_registry); LTTNG_ASSERT(consumer); ASSERT_RCU_READ_LOCKED(); - pthread_mutex_lock(®istry->_lock); - if (registry->_metadata_closed) { + if (locked_registry->_metadata_closed) { ret_val = -EPIPE; goto error; } /* Get consumer socket to use to push the metadata.*/ - socket = consumer_find_socket_by_bitness(registry->_bits_per_long, + socket = consumer_find_socket_by_bitness(locked_registry->abi.bits_per_long, consumer); if (!socket) { ret_val = -1; goto error; } - ret = ust_app_push_metadata(registry, socket, 0); + ret = ust_app_push_metadata(locked_registry, socket, 0); if (ret < 0) { ret_val = ret; goto error; } - pthread_mutex_unlock(®istry->_lock); return 0; error: - pthread_mutex_unlock(®istry->_lock); return ret_val; } @@ -846,39 +872,17 @@ error: * * Return 0 on success else a negative value. */ -static int close_metadata(ust_registry_session *registry, +static int close_metadata(uint64_t metadata_key, unsigned int consumer_bitness, struct consumer_output *consumer) { int ret; struct consumer_socket *socket; - uint64_t metadata_key; - bool registry_was_already_closed; + lttng::urcu::read_lock_guard read_lock_guard; - LTTNG_ASSERT(registry); LTTNG_ASSERT(consumer); - rcu_read_lock(); - - pthread_mutex_lock(®istry->_lock); - metadata_key = registry->_metadata_key; - registry_was_already_closed = registry->_metadata_closed; - if (metadata_key != 0) { - /* - * Metadata closed. Even on error this means that the consumer - * is not responding or not found so either way a second close - * should NOT be emit for this registry. - */ - registry->_metadata_closed = true; - } - pthread_mutex_unlock(®istry->_lock); - - if (metadata_key == 0 || registry_was_already_closed) { - ret = 0; - goto end; - } - - /* Get consumer socket to use to push the metadata.*/ - socket = consumer_find_socket_by_bitness(registry->_bits_per_long, + /* Get consumer socket to use to push the metadata. */ + socket = consumer_find_socket_by_bitness(consumer_bitness, consumer); if (!socket) { ret = -1; @@ -891,7 +895,6 @@ static int close_metadata(ust_registry_session *registry, } end: - rcu_read_unlock(); return ret; } @@ -918,7 +921,6 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess, int ret; struct lttng_ht_iter iter; struct ust_app_channel *ua_chan; - ust_registry_session *registry; LTTNG_ASSERT(ua_sess); ASSERT_RCU_READ_LOCKED(); @@ -928,12 +930,21 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess, LTTNG_ASSERT(!ua_sess->deleted); ua_sess->deleted = true; - registry = get_session_registry(ua_sess); + auto locked_registry = get_locked_session_registry(ua_sess); /* Registry can be null on error path during initialization. */ - if (registry) { + if (locked_registry) { /* Push metadata for application before freeing the application. */ - (void) push_metadata(registry, ua_sess->consumer); + (void) push_metadata(locked_registry, ua_sess->consumer); + } + cds_lfht_for_each_entry(ua_sess->channels->ht, &iter.iter, ua_chan, + node.node) { + ret = lttng_ht_del(ua_sess->channels, &iter); + LTTNG_ASSERT(!ret); + delete_ust_app_channel(sock, ua_chan, app, locked_registry); + } + + if (locked_registry) { /* * Don't ask to close metadata for global per UID buffers. Close * metadata only on destroy trace session in this case. Also, the @@ -941,16 +952,17 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess, * close so don't send a close command if closed. */ if (ua_sess->buffer_type != LTTNG_BUFFER_PER_UID) { - /* And ask to close it for this session registry. */ - (void) close_metadata(registry, ua_sess->consumer); - } - } + const auto metadata_key = locked_registry->_metadata_key; + const auto consumer_bitness = locked_registry->abi.bits_per_long; - cds_lfht_for_each_entry(ua_sess->channels->ht, &iter.iter, ua_chan, - node.node) { - ret = lttng_ht_del(ua_sess->channels, &iter); - LTTNG_ASSERT(!ret); - delete_ust_app_channel(sock, ua_chan, app); + if (!locked_registry->_metadata_closed && metadata_key != 0) { + locked_registry->_metadata_closed = true; + } + + /* Release lock before communication, see comments in close_metadata(). */ + locked_registry.reset(); + (void) close_metadata(metadata_key, consumer_bitness, ua_sess->consumer); + } } /* In case of per PID, the registry is kept in the session. */ @@ -1984,8 +1996,6 @@ static int send_channel_pid_to_ust(struct ust_app *app, cds_list_del(&stream->list); delete_ust_app_stream(-1, stream, app); } - /* Flag the channel that it is sent to the application. */ - ua_chan->is_sent = 1; error: health_code_update(); @@ -2399,7 +2409,7 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, LTTNG_OPTIONAL_SET(&ua_sess->effective_credentials.uid, usess->uid); LTTNG_OPTIONAL_SET(&ua_sess->effective_credentials.gid, usess->gid); ua_sess->buffer_type = usess->buffer_type; - ua_sess->bits_per_long = app->bits_per_long; + ua_sess->bits_per_long = app->abi.bits_per_long; /* There is only one consumer object per session possible. */ consumer_output_get(usess->consumer); @@ -2420,7 +2430,7 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, ret = snprintf(ua_sess->path, sizeof(ua_sess->path), DEFAULT_UST_TRACE_UID_PATH, lttng_credentials_get_uid(&ua_sess->real_credentials), - app->bits_per_long); + app->abi.bits_per_long); break; default: abort(); @@ -2448,7 +2458,7 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, case LTTNG_BUFFER_PER_UID: ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path), "/" DEFAULT_UST_TRACE_UID_PATH, - app->uid, app->bits_per_long); + app->uid, app->abi.bits_per_long); break; default: abort(); @@ -2536,12 +2546,9 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess, } /* Initialize registry. */ - reg_pid->registry->reg.ust = ust_registry_session_per_pid_create(app, - app->bits_per_long, app->uint8_t_alignment, - app->uint16_t_alignment, app->uint32_t_alignment, - app->uint64_t_alignment, app->long_alignment, - app->byte_order, app->version.major, app->version.minor, - reg_pid->root_shm_path, reg_pid->shm_path, + reg_pid->registry->reg.ust = ust_registry_session_per_pid_create(app, app->abi, + app->version.major, app->version.minor, reg_pid->root_shm_path, + reg_pid->shm_path, lttng_credentials_get_uid(&ua_sess->effective_credentials), lttng_credentials_get_gid(&ua_sess->effective_credentials), ua_sess->tracing_id); @@ -2588,15 +2595,15 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, rcu_read_lock(); - reg_uid = buffer_reg_uid_find(usess->id, app->bits_per_long, app->uid); + reg_uid = buffer_reg_uid_find(usess->id, app->abi.bits_per_long, app->uid); if (!reg_uid) { /* * This is the create channel path meaning that if there is NO * registry available, we have to create one for this session. */ - ret = buffer_reg_uid_create(usess->id, app->bits_per_long, app->uid, - LTTNG_DOMAIN_UST, ®_uid, - ua_sess->root_shm_path, ua_sess->shm_path); + ret = buffer_reg_uid_create(usess->id, app->abi.bits_per_long, app->uid, + LTTNG_DOMAIN_UST, ®_uid, ua_sess->root_shm_path, + ua_sess->shm_path); if (ret < 0) { goto error; } @@ -2605,14 +2612,9 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, } /* Initialize registry. */ - reg_uid->registry->reg.ust = ust_registry_session_per_uid_create( - app->bits_per_long, app->uint8_t_alignment, - app->uint16_t_alignment, app->uint32_t_alignment, - app->uint64_t_alignment, app->long_alignment, - app->byte_order, app->version.major, - app->version.minor, reg_uid->root_shm_path, - reg_uid->shm_path, usess->uid, usess->gid, - ua_sess->tracing_id, app->uid); + reg_uid->registry->reg.ust = ust_registry_session_per_uid_create(app->abi, + app->version.major, app->version.minor, reg_uid->root_shm_path, + reg_uid->shm_path, usess->uid, usess->gid, ua_sess->tracing_id, app->uid); if (!reg_uid->registry->reg.ust) { /* * reg_uid->registry->reg.ust is NULL upon error, so we need to @@ -2983,7 +2985,7 @@ error: */ static int do_consumer_create_channel(struct ltt_ust_session *usess, struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan, - int bitness, ust_registry_session *registry) + int bitness, lsu::registry_session *registry) { int ret; unsigned int nb_fd = 0; @@ -3218,11 +3220,14 @@ static int create_buffer_reg_channel(struct buffer_reg_session *reg_sess, buf_reg_chan->num_subbuf = ua_chan->attr.num_subbuf; /* Create and add a channel registry to session. */ - ret = ust_registry_channel_add(reg_sess->reg.ust, - ua_chan->tracing_channel_id); - if (ret < 0) { + try { + reg_sess->reg.ust->add_channel(ua_chan->tracing_channel_id); + } catch (const std::exception& ex) { + ERR("Failed to add a channel registry to userspace registry session: %s", ex.what()); + ret = -1; goto error; } + buffer_reg_channel_add(reg_sess, buf_reg_chan); if (regp) { @@ -3352,7 +3357,6 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *buf_reg_chan, */ (void) release_ust_app_stream(-1, &stream, app); } - ua_chan->is_sent = 1; error_stream_unlock: pthread_mutex_unlock(&buf_reg_chan->stream_list_lock); @@ -3377,7 +3381,6 @@ static int create_channel_per_uid(struct ust_app *app, struct buffer_reg_channel *buf_reg_chan; struct ltt_session *session = NULL; enum lttng_error_code notification_ret; - struct ust_registry_channel *ust_reg_chan; LTTNG_ASSERT(app); LTTNG_ASSERT(usess); @@ -3387,7 +3390,7 @@ static int create_channel_per_uid(struct ust_app *app, DBG("UST app creating channel %s with per UID buffers", ua_chan->name); - reg_uid = buffer_reg_uid_find(usess->id, app->bits_per_long, app->uid); + reg_uid = buffer_reg_uid_find(usess->id, app->abi.bits_per_long, app->uid); /* * The session creation handles the creation of this global registry * object. If none can be find, there is a code flow problem or a @@ -3419,7 +3422,7 @@ static int create_channel_per_uid(struct ust_app *app, * ust app channel object with all streams and data object. */ ret = do_consumer_create_channel(usess, ua_sess, ua_chan, - app->bits_per_long, reg_uid->registry->reg.ust); + app->abi.bits_per_long, reg_uid->registry->reg.ust); if (ret < 0) { ERR("Error creating UST channel \"%s\" on the consumer daemon", ua_chan->name); @@ -3428,8 +3431,12 @@ static int create_channel_per_uid(struct ust_app *app, * Let's remove the previously created buffer registry channel so * it's not visible anymore in the session registry. */ - ust_registry_channel_del_free(reg_uid->registry->reg.ust, - ua_chan->tracing_channel_id, false); + auto locked_registry = reg_uid->registry->reg.ust->lock(); + try { + locked_registry->remove_channel(ua_chan->tracing_channel_id, false); + } catch (const std::exception &ex) { + DBG("Could not find channel for removal: %s", ex.what()); + } buffer_reg_channel_remove(reg_uid->registry, buf_reg_chan); buffer_reg_channel_destroy(buf_reg_chan, LTTNG_DOMAIN_UST); goto error; @@ -3445,15 +3452,14 @@ static int create_channel_per_uid(struct ust_app *app, goto error; } - /* Notify the notification subsystem of the channel's creation. */ - pthread_mutex_lock(®_uid->registry->reg.ust->_lock); - ust_reg_chan = ust_registry_channel_find(reg_uid->registry->reg.ust, - ua_chan->tracing_channel_id); - LTTNG_ASSERT(ust_reg_chan); - ust_reg_chan->consumer_key = ua_chan->key; - ust_reg_chan = NULL; - pthread_mutex_unlock(®_uid->registry->reg.ust->_lock); + { + auto locked_registry = reg_uid->registry->reg.ust->lock(); + auto& ust_reg_chan = locked_registry->get_channel(ua_chan->tracing_channel_id); + ust_reg_chan._consumer_key = ua_chan->key; + } + + /* Notify the notification subsystem of the channel's creation. */ notification_ret = notification_thread_command_add_channel( the_notification_thread_handle, session->name, lttng_credentials_get_uid( @@ -3498,11 +3504,10 @@ static int create_channel_per_pid(struct ust_app *app, struct ust_app_channel *ua_chan) { int ret; - ust_registry_session *registry; + lsu::registry_session *registry; enum lttng_error_code cmd_ret; struct ltt_session *session = NULL; uint64_t chan_reg_key; - struct ust_registry_channel *ust_reg_chan; LTTNG_ASSERT(app); LTTNG_ASSERT(usess); @@ -3518,10 +3523,12 @@ static int create_channel_per_pid(struct ust_app *app, LTTNG_ASSERT(registry); /* Create and add a new channel registry to session. */ - ret = ust_registry_channel_add(registry, ua_chan->key); - if (ret < 0) { - ERR("Error creating the UST channel \"%s\" registry instance", - ua_chan->name); + try { + registry->add_channel(ua_chan->key); + } catch (const std::exception& ex) { + ERR("Error creating the UST channel \"%s\" registry instance: %s", ua_chan->name, + ex.what()); + ret = -1; goto error; } @@ -3532,7 +3539,7 @@ static int create_channel_per_pid(struct ust_app *app, /* Create and get channel on the consumer side. */ ret = do_consumer_create_channel(usess, ua_sess, ua_chan, - app->bits_per_long, registry); + app->abi.bits_per_long, registry); if (ret < 0) { ERR("Error creating UST channel \"%s\" on the consumer daemon", ua_chan->name); @@ -3548,11 +3555,12 @@ static int create_channel_per_pid(struct ust_app *app, } chan_reg_key = ua_chan->key; - pthread_mutex_lock(®istry->_lock); - ust_reg_chan = ust_registry_channel_find(registry, chan_reg_key); - LTTNG_ASSERT(ust_reg_chan); - ust_reg_chan->consumer_key = ua_chan->key; - pthread_mutex_unlock(®istry->_lock); + { + auto locked_registry = registry->lock(); + + auto& ust_reg_chan = locked_registry->get_channel(chan_reg_key); + ust_reg_chan._consumer_key = ua_chan->key; + } cmd_ret = notification_thread_command_add_channel( the_notification_thread_handle, session->name, @@ -3570,7 +3578,12 @@ static int create_channel_per_pid(struct ust_app *app, error_remove_from_registry: if (ret) { - ust_registry_channel_del_free(registry, ua_chan->key, false); + try { + auto locked_registry = registry->lock(); + locked_registry->remove_channel(ua_chan->key, false); + } catch (const std::exception& ex) { + DBG("Could not find channel for removal: %s", ex.what()); + } } error: rcu_read_unlock(); @@ -3819,7 +3832,6 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, int ret = 0; struct ust_app_channel *metadata; struct consumer_socket *socket; - ust_registry_session *registry; struct ltt_session *session = NULL; LTTNG_ASSERT(ua_sess); @@ -3827,14 +3839,12 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, LTTNG_ASSERT(consumer); ASSERT_RCU_READ_LOCKED(); - registry = get_session_registry(ua_sess); + auto locked_registry = get_locked_session_registry(ua_sess); /* The UST app session is held registry shall not be null. */ - LTTNG_ASSERT(registry); - - pthread_mutex_lock(®istry->_lock); + LTTNG_ASSERT(locked_registry); /* Metadata already exists for this registry or it was closed previously */ - if (registry->_metadata_key || registry->_metadata_closed) { + if (locked_registry->_metadata_key || locked_registry->_metadata_closed) { ret = 0; goto error; } @@ -3857,7 +3867,7 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, } /* Get the right consumer socket for the application. */ - socket = consumer_find_socket_by_bitness(app->bits_per_long, consumer); + socket = consumer_find_socket_by_bitness(app->abi.bits_per_long, consumer); if (!socket) { ret = -EINVAL; goto error_consumer; @@ -3869,7 +3879,7 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, * consumer requesting the metadata and the ask_channel call on our side * did not returned yet. */ - registry->_metadata_key = metadata->key; + locked_registry->_metadata_key = metadata->key; session = session_find_by_id(ua_sess->tracing_id); LTTNG_ASSERT(session); @@ -3883,10 +3893,10 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, * consumer. */ ret = ust_consumer_ask_channel(ua_sess, metadata, consumer, socket, - registry, session->current_trace_chunk); + locked_registry.get(), session->current_trace_chunk); if (ret < 0) { /* Nullify the metadata key so we don't try to close it later on. */ - registry->_metadata_key = 0; + locked_registry->_metadata_key = 0; goto error_consumer; } @@ -3899,7 +3909,7 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, ret = consumer_setup_metadata(socket, metadata->key); if (ret < 0) { /* Nullify the metadata key so we don't try to close it later on. */ - registry->_metadata_key = 0; + locked_registry->_metadata_key = 0; goto error_consumer; } @@ -3908,9 +3918,8 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, error_consumer: lttng_fd_put(LTTNG_FD_APPS, 1); - delete_ust_app_channel(-1, metadata, app); + delete_ust_app_channel(-1, metadata, app, locked_registry); error: - pthread_mutex_unlock(®istry->_lock); if (session) { session_put(session); } @@ -4003,13 +4012,17 @@ struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock) lta->uid = msg->uid; lta->gid = msg->gid; - lta->bits_per_long = msg->bits_per_long; - lta->uint8_t_alignment = msg->uint8_t_alignment; - lta->uint16_t_alignment = msg->uint16_t_alignment; - lta->uint32_t_alignment = msg->uint32_t_alignment; - lta->uint64_t_alignment = msg->uint64_t_alignment; - lta->long_alignment = msg->long_alignment; - lta->byte_order = msg->byte_order; + lta->abi = { + .bits_per_long = msg->bits_per_long, + .long_alignment = msg->long_alignment, + .uint8_t_alignment = msg->uint8_t_alignment, + .uint16_t_alignment = msg->uint16_t_alignment, + .uint32_t_alignment = msg->uint32_t_alignment, + .uint64_t_alignment = msg->uint64_t_alignment, + .byte_order = msg->byte_order == LITTLE_ENDIAN ? + lttng::sessiond::trace::byte_order::LITTLE_ENDIAN_ : + lttng::sessiond::trace::byte_order::BIG_ENDIAN_, + }; lta->v_major = msg->major; lta->v_minor = msg->minor; @@ -4268,8 +4281,6 @@ void ust_app_unregister(int sock) */ cds_lfht_for_each_entry(lta->sessions->ht, &iter.iter, ua_sess, node.node) { - ust_registry_session *registry; - ret = lttng_ht_del(lta->sessions, &iter); if (ret) { /* The session was already removed so scheduled for teardown. */ @@ -4302,10 +4313,10 @@ void ust_app_unregister(int sock) * The close metadata below nullifies the metadata pointer in the * session so the delete session will NOT push/close a second time. */ - registry = get_session_registry(ua_sess); - if (registry) { + auto locked_registry = get_locked_session_registry(ua_sess); + if (locked_registry) { /* Push metadata for application before freeing the application. */ - (void) push_metadata(registry, ua_sess->consumer); + (void) push_metadata(locked_registry, ua_sess->consumer); /* * Don't ask to close metadata for global per UID buffers. Close @@ -4314,8 +4325,18 @@ void ust_app_unregister(int sock) * close so don't send a close command if closed. */ if (ua_sess->buffer_type != LTTNG_BUFFER_PER_UID) { - /* And ask to close it for this session registry. */ - (void) close_metadata(registry, ua_sess->consumer); + const auto metadata_key = locked_registry->_metadata_key; + const auto consumer_bitness = locked_registry->abi.bits_per_long; + + if (!locked_registry->_metadata_closed && metadata_key != 0) { + locked_registry->_metadata_closed = true; + } + + /* Release lock before communication, see comments in close_metadata(). */ + locked_registry.reset(); + (void) close_metadata(metadata_key, consumer_bitness, ua_sess->consumer); + } else { + locked_registry.reset(); } } cds_list_add(&ua_sess->teardown_node, <a->teardown_head); @@ -5210,7 +5231,6 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app) { int ret = 0; struct ust_app_session *ua_sess; - ust_registry_session *registry; DBG("Stopping tracing for ust app pid %d", app->pid); @@ -5287,13 +5307,15 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app) health_code_update(); - registry = get_session_registry(ua_sess); + { + auto locked_registry = get_locked_session_registry(ua_sess); - /* The UST app session is held registry shall not be null. */ - LTTNG_ASSERT(registry); + /* The UST app session is held registry shall not be null. */ + LTTNG_ASSERT(locked_registry); - /* Push metadata for application before freeing the application. */ - (void) push_metadata(registry, ua_sess->consumer); + /* Push metadata for application before freeing the application. */ + (void) push_metadata(locked_registry, ua_sess->consumer); + } end_unlock: pthread_mutex_unlock(&ua_sess->lock); @@ -5335,7 +5357,7 @@ int ust_app_flush_app_session(struct ust_app *app, health_code_update(); /* Flushing buffers */ - socket = consumer_find_socket_by_bitness(app->bits_per_long, + socket = consumer_find_socket_by_bitness(app->abi.bits_per_long, ua_sess->consumer); /* Flush buffers and push metadata. */ @@ -5392,7 +5414,7 @@ int ust_app_flush_session(struct ltt_ust_session *usess) /* Flush all per UID buffers associated to that session. */ cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) { - ust_registry_session *ust_session_reg; + lsu::registry_session *ust_session_reg; struct buffer_reg_channel *buf_reg_chan; struct consumer_socket *socket; @@ -5416,7 +5438,8 @@ int ust_app_flush_session(struct ltt_ust_session *usess) ust_session_reg = reg->registry->reg.ust; /* Push metadata. */ - (void) push_metadata(ust_session_reg, usess->consumer); + auto locked_registry = ust_session_reg->lock(); + (void) push_metadata(locked_registry, usess->consumer); } break; } @@ -5471,11 +5494,11 @@ int ust_app_clear_quiescent_app_session(struct ust_app *app, health_code_update(); - socket = consumer_find_socket_by_bitness(app->bits_per_long, + socket = consumer_find_socket_by_bitness(app->abi.bits_per_long, ua_sess->consumer); if (!socket) { ERR("Failed to find consumer (%" PRIu32 ") socket", - app->bits_per_long); + app->abi.bits_per_long); ret = -1; goto end_unlock; } @@ -6337,106 +6360,6 @@ error: return ua_chan; } -/* - * Fixup legacy context fields for comparison: - * - legacy array becomes array_nestable, - * - legacy struct becomes struct_nestable, - * - legacy variant becomes variant_nestable, - * legacy sequences are not emitted in LTTng-UST contexts. - */ -static int ust_app_fixup_legacy_context_fields(size_t *_nr_fields, - struct lttng_ust_ctl_field **_fields) -{ - struct lttng_ust_ctl_field *fields = *_fields, *new_fields = NULL; - size_t nr_fields = *_nr_fields, new_nr_fields = 0, i, j; - bool found = false; - int ret = 0; - - for (i = 0; i < nr_fields; i++) { - const struct lttng_ust_ctl_field *field = &fields[i]; - - switch (field->type.atype) { - case lttng_ust_ctl_atype_sequence: - ERR("Unexpected legacy sequence context."); - ret = -EINVAL; - goto end; - case lttng_ust_ctl_atype_array: - switch (field->type.u.legacy.array.elem_type.atype) { - case lttng_ust_ctl_atype_integer: - break; - default: - ERR("Unexpected legacy array element type in context."); - ret = -EINVAL; - goto end; - } - found = true; - /* One field for array_nested, one field for elem type. */ - new_nr_fields += 2; - break; - - case lttng_ust_ctl_atype_struct: /* Fallthrough */ - case lttng_ust_ctl_atype_variant: - found = true; - new_nr_fields++; - break; - default: - new_nr_fields++; - break; - } - } - if (!found) { - goto end; - } - - new_fields = calloc(new_nr_fields); - if (!new_fields) { - ret = -ENOMEM; - goto end; - } - - for (i = 0, j = 0; i < nr_fields; i++, j++) { - const struct lttng_ust_ctl_field *field = &fields[i]; - struct lttng_ust_ctl_field *new_field = &new_fields[j]; - - switch (field->type.atype) { - case lttng_ust_ctl_atype_array: - /* One field for array_nested, one field for elem type. */ - strncpy(new_field->name, field->name, LTTNG_UST_ABI_SYM_NAME_LEN - 1); - new_field->type.atype = lttng_ust_ctl_atype_array_nestable; - new_field->type.u.array_nestable.length = field->type.u.legacy.array.length; - new_field->type.u.array_nestable.alignment = 0; - new_field = &new_fields[++j]; /* elem type */ - new_field->type.atype = field->type.u.legacy.array.elem_type.atype; - assert(new_field->type.atype == lttng_ust_ctl_atype_integer); - new_field->type.u.integer = field->type.u.legacy.array.elem_type.u.basic.integer; - break; - case lttng_ust_ctl_atype_struct: - strncpy(new_field->name, field->name, LTTNG_UST_ABI_SYM_NAME_LEN - 1); - new_field->type.atype = lttng_ust_ctl_atype_struct_nestable; - new_field->type.u.struct_nestable.nr_fields = field->type.u.legacy._struct.nr_fields; - new_field->type.u.struct_nestable.alignment = 0; - break; - case lttng_ust_ctl_atype_variant: - strncpy(new_field->name, field->name, LTTNG_UST_ABI_SYM_NAME_LEN - 1); - new_field->type.atype = lttng_ust_ctl_atype_variant_nestable; - new_field->type.u.variant_nestable.nr_choices = field->type.u.legacy.variant.nr_choices; - strncpy(new_field->type.u.variant_nestable.tag_name, - field->type.u.legacy.variant.tag_name, - LTTNG_UST_ABI_SYM_NAME_LEN - 1); - new_field->type.u.variant_nestable.alignment = 0; - break; - default: - *new_field = *field; - break; - } - } - free(fields); - *_fields = new_fields; - *_nr_fields = new_nr_fields; -end: - return ret; -} - /* * Reply to a register channel notification from an application on the notify * socket. The channel metadata is also created. @@ -6445,47 +6368,45 @@ end: * * On success 0 is returned else a negative value. */ -static int reply_ust_register_channel(int sock, int cobjd, - size_t nr_fields, struct lttng_ust_ctl_field *fields) +static int handle_app_register_channel_notification(int sock, + int cobjd, + struct lttng_ust_ctl_field *raw_context_fields, + size_t context_field_count) { int ret, ret_code = 0; uint32_t chan_id; uint64_t chan_reg_key; - enum lttng_ust_ctl_channel_header type = LTTNG_UST_CTL_CHANNEL_HEADER_UNKNOWN; struct ust_app *app; struct ust_app_channel *ua_chan; struct ust_app_session *ua_sess; - ust_registry_session *registry; - struct ust_registry_channel *ust_reg_chan; + auto ust_ctl_context_fields = lttng::make_unique_wrapper( + raw_context_fields); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock_guard; /* Lookup application. If not found, there is a code flow error. */ app = find_app_by_notify_sock(sock); if (!app) { DBG("Application socket %d is being torn down. Abort event notify", sock); - ret = -1; - goto error_rcu_unlock; + return -1; } /* Lookup channel by UST object descriptor. */ ua_chan = find_channel_by_objd(app, cobjd); if (!ua_chan) { DBG("Application channel is being torn down. Abort event notify"); - ret = 0; - goto error_rcu_unlock; + return 0; } LTTNG_ASSERT(ua_chan->session); ua_sess = ua_chan->session; /* Get right session registry depending on the session buffer type. */ - registry = get_session_registry(ua_sess); - if (!registry) { + auto locked_registry_session = get_locked_session_registry(ua_sess); + if (!locked_registry_session) { DBG("Application session is being torn down. Abort event notify"); - ret = 0; - goto error_rcu_unlock; + return 0; }; /* Depending on the buffer type, a different channel key is used. */ @@ -6495,42 +6416,36 @@ static int reply_ust_register_channel(int sock, int cobjd, chan_reg_key = ua_chan->key; } - pthread_mutex_lock(®istry->_lock); - - ust_reg_chan = ust_registry_channel_find(registry, chan_reg_key); - LTTNG_ASSERT(ust_reg_chan); + auto& ust_reg_chan = locked_registry_session->get_channel(chan_reg_key); /* Channel id is set during the object creation. */ - chan_id = ust_reg_chan->chan_id; + chan_id = ust_reg_chan.id; - ret = ust_app_fixup_legacy_context_fields(&nr_fields, &fields); - if (ret < 0) { - ERR("Registering application channel due to legacy context fields fixup error: pid = %d, sock = %d", - app->pid, app->sock); - ret_code = -EINVAL; - goto reply; - } - if (!ust_reg_chan->register_done) { - /* - * TODO: eventually use the registry event count for - * this channel to better guess header type for per-pid - * buffers. - */ - type = LTTNG_UST_CTL_CHANNEL_HEADER_LARGE; - ust_reg_chan->nr_ctx_fields = nr_fields; - ust_reg_chan->ctx_fields = fields; - fields = NULL; - ust_reg_chan->header_type = type; + /* + * The application returns the typing information of the channel's + * context fields. In per-PID buffering mode, this is the first and only + * time we get this information. It is our chance to finalize the + * initialiation of the channel and serialize it's layout's description + * to the trace's metadata. + * + * However, in per-UID buffering mode, every application will provide + * this information (redundantly). The first time will allow us to + * complete the initialization. The following times, we simply validate + * that all apps provide the same typing for the context fields as a + * sanity check. + */ + lst::type::cuptr context_fields = lttng::make_unique(0, + lsu::create_trace_fields_from_ust_ctl_fields(*locked_registry_session, + ust_ctl_context_fields.get(), context_field_count)); + + if (!ust_reg_chan.is_registered()) { + ust_reg_chan.set_context(std::move(context_fields)); } else { - /* Get current already assigned values. */ - type = ust_reg_chan->header_type; /* * Validate that the context fields match between * registry and newcoming application. */ - if (!match_lttng_ust_ctl_field_array(ust_reg_chan->ctx_fields, - ust_reg_chan->nr_ctx_fields, - fields, nr_fields)) { + if (ust_reg_chan.get_context() != *context_fields) { ERR("Registering application channel due to context field mismatch: pid = %d, sock = %d", app->pid, app->sock); ret_code = -EINVAL; @@ -6539,8 +6454,8 @@ static int reply_ust_register_channel(int sock, int cobjd, } /* Append to metadata */ - if (!ust_reg_chan->metadata_dumped) { - ret_code = ust_metadata_channel_statedump(registry, ust_reg_chan); + if (!ust_reg_chan._metadata_dumped) { + /*ret_code = ust_metadata_channel_statedump(registry, ust_reg_chan);*/ if (ret_code) { ERR("Error appending channel metadata (errno = %d)", ret_code); goto reply; @@ -6549,10 +6464,14 @@ static int reply_ust_register_channel(int sock, int cobjd, reply: DBG3("UST app replying to register channel key %" PRIu64 - " with id %u, type = %d, ret = %d", chan_reg_key, chan_id, type, + " with id %u, ret = %d", chan_reg_key, chan_id, ret_code); - ret = lttng_ust_ctl_reply_register_channel(sock, chan_id, type, ret_code); + ret = lttng_ust_ctl_reply_register_channel(sock, chan_id, + ust_reg_chan.header_type == lst::stream_class::header_type::COMPACT ? + LTTNG_UST_CTL_CHANNEL_HEADER_COMPACT : + LTTNG_UST_CTL_CHANNEL_HEADER_LARGE, + ret_code); if (ret < 0) { if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { DBG3("UST app reply channel failed. Application died: pid = %d, sock = %d", @@ -6564,17 +6483,13 @@ reply: ERR("UST app reply channel failed with ret %d: pid = %d, sock = %d", ret, app->pid, app->sock); } - goto error; + + return ret; } - /* This channel registry registration is completed. */ - ust_reg_chan->register_done = 1; + /* This channel registry's registration is completed. */ + ust_reg_chan.set_as_registered(); -error: - pthread_mutex_unlock(®istry->_lock); -error_rcu_unlock: - rcu_read_unlock(); - free(fields); return ret; } @@ -6587,9 +6502,9 @@ error_rcu_unlock: * * On success 0 is returned else a negative value. */ -static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name, - char *sig, size_t nr_fields, struct lttng_ust_ctl_field *fields, - int loglevel_value, char *model_emf_uri) +static int add_event_ust_registry(int sock, int sobjd, int cobjd, const char *name, + char *raw_signature, size_t nr_fields, struct lttng_ust_ctl_field *raw_fields, + int loglevel_value, char *raw_model_emf_uri) { int ret, ret_code; uint32_t event_id = 0; @@ -6597,57 +6512,69 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name, struct ust_app *app; struct ust_app_channel *ua_chan; struct ust_app_session *ua_sess; - ust_registry_session *registry; - - rcu_read_lock(); + lttng::urcu::read_lock_guard rcu_lock; + auto signature = lttng::make_unique_wrapper(raw_signature); + auto fields = lttng::make_unique_wrapper(raw_fields); + auto model_emf_uri = lttng::make_unique_wrapper(raw_model_emf_uri); /* Lookup application. If not found, there is a code flow error. */ app = find_app_by_notify_sock(sock); if (!app) { DBG("Application socket %d is being torn down. Abort event notify", sock); - ret = -1; - goto error_rcu_unlock; + return -1; } /* Lookup channel by UST object descriptor. */ ua_chan = find_channel_by_objd(app, cobjd); if (!ua_chan) { DBG("Application channel is being torn down. Abort event notify"); - ret = 0; - goto error_rcu_unlock; + return 0; } LTTNG_ASSERT(ua_chan->session); ua_sess = ua_chan->session; - registry = get_session_registry(ua_sess); - if (!registry) { - DBG("Application session is being torn down. Abort event notify"); - ret = 0; - goto error_rcu_unlock; - } - if (ua_sess->buffer_type == LTTNG_BUFFER_PER_UID) { chan_reg_key = ua_chan->tracing_channel_id; } else { chan_reg_key = ua_chan->key; } - pthread_mutex_lock(®istry->_lock); - - /* - * From this point on, this call acquires the ownership of the sig, fields - * and model_emf_uri meaning any free are done inside it if needed. These - * three variables MUST NOT be read/write after this. - */ - ret_code = ust_registry_create_event(registry, chan_reg_key, - sobjd, cobjd, name, sig, nr_fields, fields, - loglevel_value, model_emf_uri, ua_sess->buffer_type, - &event_id, app); - sig = NULL; - fields = NULL; - model_emf_uri = NULL; + { + auto locked_registry = get_locked_session_registry(ua_sess); + if (locked_registry) { + /* + * From this point on, this call acquires the ownership of the signature, + * fields and model_emf_uri meaning any free are done inside it if needed. + * These three variables MUST NOT be read/write after this. + */ + try { + auto& channel = locked_registry->get_channel(chan_reg_key); + + /* event_id is set on success. */ + channel.add_event(sobjd, cobjd, name, signature.get(), + lsu::create_trace_fields_from_ust_ctl_fields( + *locked_registry, fields.get(), + nr_fields), + loglevel_value, + model_emf_uri.get() ? + nonstd::optional( + model_emf_uri.get()) : + nonstd::nullopt, + ua_sess->buffer_type, *app, event_id); + ret_code = 0; + } catch (const std::exception& ex) { + ERR("Failed to add event `%s` to registry session: %s", name, + ex.what()); + /* Inform the application of the error; don't return directly. */ + ret_code = -EINVAL; + } + } else { + DBG("Application session is being torn down. Abort event notify"); + return 0; + } + } /* * The return value is returned to ustctl so in case of an error, the @@ -6670,19 +6597,11 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name, * No need to wipe the create event since the application socket will * get close on error hence cleaning up everything by itself. */ - goto error; + return ret; } DBG3("UST registry event %s with id %" PRId32 " added successfully", name, event_id); - -error: - pthread_mutex_unlock(®istry->_lock); -error_rcu_unlock: - rcu_read_unlock(); - free(sig); - free(fields); - free(model_emf_uri); return ret; } @@ -6694,16 +6613,16 @@ error_rcu_unlock: * * On success 0 is returned else a negative value. */ -static int add_enum_ust_registry(int sock, int sobjd, char *name, - struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries) +static int add_enum_ust_registry(int sock, int sobjd, const char *name, + struct lttng_ust_ctl_enum_entry *raw_entries, size_t nr_entries) { - int ret = 0, ret_code; + int ret = 0; struct ust_app *app; struct ust_app_session *ua_sess; - ust_registry_session *registry; uint64_t enum_id = -1ULL; - - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock_guard; + auto entries = lttng::make_unique_wrapper( + raw_entries); /* Lookup application. If not found, there is a code flow error. */ app = find_app_by_notify_sock(sock); @@ -6711,9 +6630,7 @@ static int add_enum_ust_registry(int sock, int sobjd, char *name, /* Return an error since this is not an error */ DBG("Application socket %d is being torn down. Aborting enum registration", sock); - free(entries); - ret = -1; - goto error_rcu_unlock; + return -1; } /* Lookup session by UST object descriptor. */ @@ -6721,34 +6638,37 @@ static int add_enum_ust_registry(int sock, int sobjd, char *name, if (!ua_sess) { /* Return an error since this is not an error */ DBG("Application session is being torn down (session not found). Aborting enum registration."); - free(entries); - goto error_rcu_unlock; + return 0; } - registry = get_session_registry(ua_sess); - if (!registry) { + auto locked_registry = get_locked_session_registry(ua_sess); + if (!locked_registry) { DBG("Application session is being torn down (registry not found). Aborting enum registration."); - free(entries); - goto error_rcu_unlock; + return 0; } - pthread_mutex_lock(®istry->_lock); - /* * From this point on, the callee acquires the ownership of * entries. The variable entries MUST NOT be read/written after * call. */ - ret_code = ust_registry_create_or_find_enum(registry, sobjd, name, - entries, nr_entries, &enum_id); - entries = NULL; + int application_reply_code; + try { + locked_registry->create_or_find_enum( + sobjd, name, entries.release(), nr_entries, &enum_id); + application_reply_code = 0; + } catch (const std::exception& ex) { + ERR("%s: %s", fmt::format("Failed to create or find enumeration provided by application: app = {}, enumeration name = {}", + *app, name).c_str(), ex.what()); + application_reply_code = -1; + } /* * The return value is returned to ustctl so in case of an error, the * application can be notified. In case of an error, it's important not to * return a negative error or else the application will get closed. */ - ret = lttng_ust_ctl_reply_register_enum(sock, enum_id, ret_code); + ret = lttng_ust_ctl_reply_register_enum(sock, enum_id, application_reply_code); if (ret < 0) { if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { DBG3("UST app reply enum failed. Application died: pid = %d, sock = %d", @@ -6764,16 +6684,11 @@ static int add_enum_ust_registry(int sock, int sobjd, char *name, * No need to wipe the create enum since the application socket will * get close on error hence cleaning up everything by itself. */ - goto error; + return ret; } DBG3("UST registry enum %s added successfully or already found", name); - -error: - pthread_mutex_unlock(®istry->_lock); -error_rcu_unlock: - rcu_read_unlock(); - return ret; + return 0; } /* @@ -6813,9 +6728,8 @@ int ust_app_recv_notify(int sock) DBG2("UST app ustctl register event received"); - ret = lttng_ust_ctl_recv_register_event(sock, &sobjd, &cobjd, name, - &loglevel_value, &sig, &nr_fields, &fields, - &model_emf_uri); + ret = lttng_ust_ctl_recv_register_event(sock, &sobjd, &cobjd, name, &loglevel_value, + &sig, &nr_fields, &fields, &model_emf_uri); if (ret < 0) { if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { DBG3("UST app recv event failed. Application died: sock = %d", @@ -6830,6 +6744,24 @@ int ust_app_recv_notify(int sock) goto error; } + { + lttng::urcu::read_lock_guard rcu_lock; + const struct ust_app *app = find_app_by_notify_sock(sock); + if (!app) { + DBG("Application socket %d is being torn down. Abort event notify", sock); + ret = -1; + goto error; + } + } + + if ((!fields && nr_fields > 0) || (fields && nr_fields == 0)) { + ERR("Invalid return value from lttng_ust_ctl_recv_register_event: fields = %p, nr_fields = %zu", + fields, nr_fields); + ret = -1; + free(fields); + goto error; + } + /* * Add event to the UST registry coming from the notify socket. This * call will free if needed the sig, fields and model_emf_uri. This @@ -6847,13 +6779,13 @@ int ust_app_recv_notify(int sock) case LTTNG_UST_CTL_NOTIFY_CMD_CHANNEL: { int sobjd, cobjd; - size_t nr_fields; - struct lttng_ust_ctl_field *fields; + size_t field_count; + struct lttng_ust_ctl_field *context_fields; DBG2("UST app ustctl register channel received"); - ret = lttng_ust_ctl_recv_register_channel(sock, &sobjd, &cobjd, &nr_fields, - &fields); + ret = lttng_ust_ctl_recv_register_channel( + sock, &sobjd, &cobjd, &field_count, &context_fields); if (ret < 0) { if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { DBG3("UST app recv channel failed. Application died: sock = %d", @@ -6862,8 +6794,8 @@ int ust_app_recv_notify(int sock) WARN("UST app recv channel failed. Communication time out: sock = %d", sock); } else { - ERR("UST app recv channel failed with ret %d: sock = %d", - ret, sock); + ERR("UST app recv channel failed with ret %d: sock = %d", ret, + sock); } goto error; } @@ -6871,10 +6803,9 @@ int ust_app_recv_notify(int sock) /* * The fields ownership are transfered to this function call meaning * that if needed it will be freed. After this, it's invalid to access - * fields or clean it up. + * fields or clean them up. */ - ret = reply_ust_register_channel(sock, cobjd, nr_fields, - fields); + ret = handle_app_register_channel_notification(sock, cobjd, context_fields, field_count); if (ret < 0) { goto error; } @@ -6906,7 +6837,7 @@ int ust_app_recv_notify(int sock) goto error; } - /* Callee assumes ownership of entries */ + /* Callee assumes ownership of entries. */ ret = add_enum_ust_registry(sock, sobjd, name, entries, nr_entries); if (ret < 0) { @@ -7103,7 +7034,7 @@ enum lttng_error_code ust_app_snapshot_record( struct lttng_ht_iter chan_iter; struct ust_app_channel *ua_chan; struct ust_app_session *ua_sess; - ust_registry_session *registry; + lsu::registry_session *registry; char pathname[PATH_MAX]; size_t consumer_path_offset = 0; @@ -7114,7 +7045,7 @@ enum lttng_error_code ust_app_snapshot_record( } /* Get the right consumer socket for the application. */ - socket = consumer_find_socket_by_bitness(app->bits_per_long, + socket = consumer_find_socket_by_bitness(app->abi.bits_per_long, output); if (!socket) { status = LTTNG_ERR_INVALID; @@ -7475,7 +7406,10 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) continue; } - (void) push_metadata(reg->registry->reg.ust, usess->consumer); + { + auto locked_registry = reg->registry->reg.ust->lock(); + (void) push_metadata(locked_registry, usess->consumer); + } ret = consumer_rotate_channel(socket, reg->registry->reg.ust->_metadata_key, @@ -7495,7 +7429,7 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) struct lttng_ht_iter chan_iter; struct ust_app_channel *ua_chan; struct ust_app_session *ua_sess; - ust_registry_session *registry; + lsu::registry_session *registry; ua_sess = lookup_session_by_app(usess, app); if (!ua_sess) { @@ -7504,7 +7438,7 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) } /* Get the right consumer socket for the application. */ - socket = consumer_find_socket_by_bitness(app->bits_per_long, + socket = consumer_find_socket_by_bitness(app->abi.bits_per_long, usess->consumer); if (!socket) { cmd_ret = LTTNG_ERR_INVALID; @@ -7534,7 +7468,11 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) } /* Rotate the metadata channel. */ - (void) push_metadata(registry, usess->consumer); + { + auto locked_registry = registry->lock(); + + (void) push_metadata(locked_registry, usess->consumer); + } ret = consumer_rotate_channel(socket, registry->_metadata_key, ua_sess->consumer, @@ -7621,7 +7559,7 @@ enum lttng_error_code ust_app_create_channel_subdirectories( cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) { struct ust_app_session *ua_sess; - ust_registry_session *registry; + lsu::registry_session *registry; ua_sess = lookup_session_by_app(usess, app); if (!ua_sess) { @@ -7718,7 +7656,10 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session) } } - (void) push_metadata(reg->registry->reg.ust, usess->consumer); + { + auto locked_registry = reg->registry->reg.ust->lock(); + (void) push_metadata(locked_registry, usess->consumer); + } /* * Clear the metadata channel. @@ -7740,7 +7681,7 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session) struct lttng_ht_iter chan_iter; struct ust_app_channel *ua_chan; struct ust_app_session *ua_sess; - ust_registry_session *registry; + lsu::registry_session *registry; ua_sess = lookup_session_by_app(usess, app); if (!ua_sess) { @@ -7749,7 +7690,7 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session) } /* Get the right consumer socket for the application. */ - socket = consumer_find_socket_by_bitness(app->bits_per_long, + socket = consumer_find_socket_by_bitness(app->abi.bits_per_long, usess->consumer); if (!socket) { cmd_ret = LTTNG_ERR_INVALID; @@ -7775,7 +7716,10 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session) } } - (void) push_metadata(registry, usess->consumer); + { + auto locked_registry = registry->lock(); + (void) push_metadata(locked_registry, usess->consumer); + } /* * Clear the metadata channel. @@ -7884,7 +7828,7 @@ enum lttng_error_code ust_app_open_packets(struct ltt_session *session) struct lttng_ht_iter chan_iter; struct ust_app_channel *ua_chan; struct ust_app_session *ua_sess; - ust_registry_session *registry; + lsu::registry_session *registry; ua_sess = lookup_session_by_app(usess, app); if (!ua_sess) { @@ -7894,7 +7838,7 @@ enum lttng_error_code ust_app_open_packets(struct ltt_session *session) /* Get the right consumer socket for the application. */ socket = consumer_find_socket_by_bitness( - app->bits_per_long, usess->consumer); + app->abi.bits_per_long, usess->consumer); if (!socket) { ret = LTTNG_ERR_FATAL; goto error;