Fix: sessiond: size-based rotation threshold exceeded in per-pid tracing (1/2)
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 27 Jun 2022 16:01:48 +0000 (12:01 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 4 Jul 2022 15:43:43 +0000 (11:43 -0400)
Issue observed
--------------

When tracing short-lived applications with buffers configured in per-pid
mode, the size-based rotation threshold is often greatly exceeded. In
the CI, this occasionally causes the size-based rotation tests to
timeout for the per-pid case.

Cause
-----

There is a scenario where a session's consumed size is miscalculated.

When an application exits during per-pid tracing, both the session and
consumer daemons notice it. The session daemon sees the application's
command pipe hanging-up, while the consumer daemon sees the
application's data-ready pipe hanging-up.

Upon handling these events, both daemons tear down their representation of
the channels.

In an ideal world, we'd want to sample the streams' "consumed_size" at
the last possible moment to get the size of all consumed data for this
stream. However, this is problematic in the following scenario:
  - the sessiond destroys the channel before the consumer daemon,
  - the consumer daemon sends a final buffer stats sample on tear down,
  - the sessiond can do nothing with the sample as it doesn't know that
    channel anymore.

(Note that the session daemon gracefully handles the case where it
doesn't know a channel.)

When applications have a short lifetime and are traced in per-PID
buffering mode, there is a high likelihood that the last buffer
statistics sample sent for a given channel will target a channel that
the session daemon has already torn down.

Solution
--------

Consumed-size conditions are somewhat special: they are bound to a
session, but they are evaluated through a per-channel event (buffer
statistics samples taken by the channels' monitoring timer).

To work around the problem of lifetime of channels, we can rely
on the fact that sessions outlive channels to perform the accounting
of the consumed size.

This patch is the first step to implement this fix: new
notification-thread commands are introduced to announce the creation and
destruction of an `ltt_session`. Currently, the notification thread
implies the existence of a session by tracking its channels' creation
and destruction.

With this change, it no longer needs to do so; session are explicitly
created and destroyed. Their unique ID is also kept stored.

The key of `sessions_ht` becomes the `id` of the session to allow
efficient look-ups on the reception of a buffer statistics sample.

The existing callsites that make use of the session's name to perform a
look-up are modified to look-up the id by name (see
sample_session_id_by_name()).

The add/remove channel commands and rotation ongoing/completed commands
are modified to refer to sessions by ID since they can assume the
notification thread knows about the session.

Note
----

In a follow-up patch, buffer statistics samples are modified to include
the session's ID and the consumed size is modified to become a "delta"
relative to the previous sample associated with a given channel.

This makes it possible to perform the accounting of a session's consumed
size beyond the lifetime of its channels.

The follow-up patch is the "core" of the fix, but it requires these
prior changes.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I865e9ac5e1a63e62123209be63957dad28c588a8

src/bin/lttng-sessiond/cmd.cpp
src/bin/lttng-sessiond/kernel-consumer.cpp
src/bin/lttng-sessiond/notification-thread-commands.cpp
src/bin/lttng-sessiond/notification-thread-commands.hpp
src/bin/lttng-sessiond/notification-thread-events.cpp
src/bin/lttng-sessiond/notification-thread-internal.hpp
src/bin/lttng-sessiond/notification-thread.hpp
src/bin/lttng-sessiond/rotation-thread.cpp
src/bin/lttng-sessiond/ust-app.cpp

index fe9656a89b8b59e1585f7693c3ca7db9cd3bf7ee..0b74920556d59230a5bf2a87adcef42590dd1627 100644 (file)
@@ -3136,6 +3136,28 @@ enum lttng_error_code cmd_create_session_from_descriptor(
                goto end;
        }
 
+       ret_code = notification_thread_command_add_session(the_notification_thread_handle,
+                       new_session->id, new_session->name, new_session->uid, new_session->gid);
+       if (ret_code != LTTNG_OK) {
+               goto end;
+       }
+
+       /* Announce the session's destruction to the notification thread when it is destroyed. */
+       ret = session_add_destroy_notifier(
+                       new_session,
+                       [](const struct ltt_session *session,
+                                       void *user_data __attribute__((unused))) {
+                               (void) notification_thread_command_remove_session(
+                                               the_notification_thread_handle, session->id);
+                       },
+                       NULL);
+       if (ret) {
+               PERROR("Failed to add notification thread command to session's destroy notifiers: session name = %s",
+                               new_session->name);
+               ret = LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
        if (!session_name) {
                ret = lttng_session_descriptor_set_session_name(descriptor,
                                new_session->name);
@@ -5609,8 +5631,7 @@ int cmd_rotate_session(struct ltt_session *session,
        chunk_being_archived = NULL;
        if (!quiet_rotation) {
                ret = notification_thread_command_session_rotation_ongoing(
-                               the_notification_thread_handle, session->name,
-                               session->uid, session->gid,
+                               the_notification_thread_handle, session->id,
                                ongoing_rotation_chunk_id);
                if (ret != LTTNG_OK) {
                        ERR("Failed to notify notification thread that a session rotation is ongoing for session %s",
index ece50de117456feddd7d653c27a8693283dbd919..b51b56c3e772e2e1a213853266f10b79f30591ab 100644 (file)
@@ -172,12 +172,9 @@ int kernel_consumer_add_channel(struct consumer_socket *sock,
        ASSERT_LOCKED(session->lock);
        ASSERT_SESSION_LIST_LOCKED();
 
-       status = notification_thread_command_add_channel(
-                       the_notification_thread_handle, session->name,
-                       ksession->uid, ksession->gid, channel->channel->name,
-                       channel->key, LTTNG_DOMAIN_KERNEL,
-                       channel->channel->attr.subbuf_size *
-                                       channel->channel->attr.num_subbuf);
+       status = notification_thread_command_add_channel(the_notification_thread_handle,
+                       session->id, channel->channel->name, channel->key, LTTNG_DOMAIN_KERNEL,
+                       channel->channel->attr.subbuf_size * channel->channel->attr.num_subbuf);
        rcu_read_unlock();
        if (status != LTTNG_OK) {
                ret = -1;
index 1de6ff58be3609d1f24690a055cfcfc756709cce..25c987b67fcb1f6cc11cab7846982a1f1c5da864 100644 (file)
@@ -160,9 +160,58 @@ end:
        return ret_code;
 }
 
+enum lttng_error_code notification_thread_command_add_session(
+               struct notification_thread_handle *handle,
+               uint64_t session_id, const char *session_name, uid_t session_uid, gid_t session_gid)
+{
+       int ret;
+       enum lttng_error_code ret_code;
+       struct notification_thread_command cmd = {};
+
+       init_notification_thread_command(&cmd);
+
+       cmd.type = NOTIFICATION_COMMAND_TYPE_ADD_SESSION;
+       cmd.parameters.add_session.session_id = session_id;
+       cmd.parameters.add_session.session_name = session_name;
+       cmd.parameters.add_session.session_uid = session_uid;
+       cmd.parameters.add_session.session_gid = session_gid;
+
+       ret = run_command_wait(handle, &cmd);
+       if (ret) {
+               ret_code = LTTNG_ERR_UNK;
+               goto end;
+       }
+       ret_code = cmd.reply_code;
+end:
+       return ret_code;
+}
+
+enum lttng_error_code notification_thread_command_remove_session(
+               struct notification_thread_handle *handle,
+               uint64_t session_id)
+{
+       int ret;
+       enum lttng_error_code ret_code;
+       struct notification_thread_command cmd = {};
+
+       init_notification_thread_command(&cmd);
+
+       cmd.type = NOTIFICATION_COMMAND_TYPE_REMOVE_SESSION;
+       cmd.parameters.remove_session.session_id = session_id;
+
+       ret = run_command_wait(handle, &cmd);
+       if (ret) {
+               ret_code = LTTNG_ERR_UNK;
+               goto end;
+       }
+       ret_code = cmd.reply_code;
+end:
+       return ret_code;
+}
+
 enum lttng_error_code notification_thread_command_add_channel(
                struct notification_thread_handle *handle,
-               char *session_name, uid_t uid, gid_t gid,
+               uint64_t session_id,
                char *channel_name, uint64_t key,
                enum lttng_domain_type domain, uint64_t capacity)
 {
@@ -173,9 +222,7 @@ enum lttng_error_code notification_thread_command_add_channel(
        init_notification_thread_command(&cmd);
 
        cmd.type = NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL;
-       cmd.parameters.add_channel.session.name = session_name;
-       cmd.parameters.add_channel.session.uid = uid;
-       cmd.parameters.add_channel.session.gid = gid;
+       cmd.parameters.add_channel.session.id = session_id;
        cmd.parameters.add_channel.channel.name = channel_name;
        cmd.parameters.add_channel.channel.key = key;
        cmd.parameters.add_channel.channel.domain = domain;
@@ -217,7 +264,7 @@ end:
 
 enum lttng_error_code notification_thread_command_session_rotation_ongoing(
                struct notification_thread_handle *handle,
-               const char *session_name, uid_t uid, gid_t gid,
+               uint64_t session_id,
                uint64_t trace_archive_chunk_id)
 {
        int ret;
@@ -227,9 +274,7 @@ enum lttng_error_code notification_thread_command_session_rotation_ongoing(
        init_notification_thread_command(&cmd);
 
        cmd.type = NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING;
-       cmd.parameters.session_rotation.session_name = session_name;
-       cmd.parameters.session_rotation.uid = uid;
-       cmd.parameters.session_rotation.gid = gid;
+       cmd.parameters.session_rotation.session_id = session_id;
        cmd.parameters.session_rotation.trace_archive_chunk_id =
                        trace_archive_chunk_id;
 
@@ -245,7 +290,7 @@ end:
 
 enum lttng_error_code notification_thread_command_session_rotation_completed(
                struct notification_thread_handle *handle,
-               const char *session_name, uid_t uid, gid_t gid,
+               uint64_t session_id,
                uint64_t trace_archive_chunk_id,
                struct lttng_trace_archive_location *location)
 {
@@ -256,9 +301,7 @@ enum lttng_error_code notification_thread_command_session_rotation_completed(
        init_notification_thread_command(&cmd);
 
        cmd.type = NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED;
-       cmd.parameters.session_rotation.session_name = session_name;
-       cmd.parameters.session_rotation.uid = uid;
-       cmd.parameters.session_rotation.gid = gid;
+       cmd.parameters.session_rotation.session_id = session_id;
        cmd.parameters.session_rotation.trace_archive_chunk_id =
                        trace_archive_chunk_id;
        cmd.parameters.session_rotation.location = location;
index 98b0abcee66942caed4cfbd5cb60c24016a3beb9..293a0b4b79ec685cd81c121b589ccd6e05941622 100644 (file)
@@ -25,6 +25,8 @@ enum notification_thread_command_type {
        NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER,
        NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL,
        NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL,
+       NOTIFICATION_COMMAND_TYPE_ADD_SESSION,
+       NOTIFICATION_COMMAND_TYPE_REMOVE_SESSION,
        NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING,
        NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED,
        NOTIFICATION_COMMAND_TYPE_ADD_TRACER_EVENT_SOURCE,
@@ -49,12 +51,21 @@ struct notification_thread_command {
                struct {
                        const struct lttng_trigger *trigger;
                } unregister_trigger;
+               /* Add session. */
+               struct {
+                       uint64_t session_id;
+                       const char *session_name;
+                       uid_t session_uid;
+                       gid_t session_gid;
+               } add_session;
+               /* Remove session. */
+               struct {
+                       uint64_t session_id;
+               } remove_session;
                /* Add channel. */
                struct {
                        struct {
-                               const char *name;
-                               uid_t uid;
-                               gid_t gid;
+                               uint64_t id;
                        } session;
                        struct {
                                const char *name;
@@ -69,9 +80,7 @@ struct notification_thread_command {
                        enum lttng_domain_type domain;
                } remove_channel;
                struct {
-                       const char *session_name;
-                       uid_t uid;
-                       gid_t gid;
+                       uint64_t session_id;
                        uint64_t trace_archive_chunk_id;
                        /* Weak reference. */
                        struct lttng_trace_archive_location *location;
@@ -121,9 +130,20 @@ enum lttng_error_code notification_thread_command_unregister_trigger(
                struct notification_thread_handle *handle,
                const struct lttng_trigger *trigger);
 
+enum lttng_error_code notification_thread_command_add_session(
+               struct notification_thread_handle *handle,
+               uint64_t session_id,
+               const char *session_name,
+               uid_t session_uid,
+               gid_t session_gid);
+
+enum lttng_error_code notification_thread_command_remove_session(
+               struct notification_thread_handle *handle,
+               uint64_t session_id);
+
 enum lttng_error_code notification_thread_command_add_channel(
                struct notification_thread_handle *handle,
-               char *session_name, uid_t session_uid, gid_t session_gid,
+               uint64_t session_id,
                char *channel_name, uint64_t key,
                enum lttng_domain_type domain, uint64_t capacity);
 
@@ -133,13 +153,13 @@ enum lttng_error_code notification_thread_command_remove_channel(
 
 enum lttng_error_code notification_thread_command_session_rotation_ongoing(
                struct notification_thread_handle *handle,
-               const char *session_name, uid_t session_uid, gid_t session_gid,
+               uint64_t session_id,
                uint64_t trace_archive_chunk_id);
 
 /* Ownership of location is transferred. */
 enum lttng_error_code notification_thread_command_session_rotation_completed(
                struct notification_thread_handle *handle,
-               const char *session_name, uid_t session_uid, gid_t session_gid,
+               uint64_t session_id,
                uint64_t trace_archive_chunk_id,
                struct lttng_trace_archive_location *location);
 
index 3c33ee79f5bafecc47d0509a42ccd387ee203607..586a9900b641419b39a0729dfa16e00459a7fed0 100644 (file)
@@ -168,13 +168,14 @@ void session_info_get(struct session_info *session_info);
 static
 void session_info_put(struct session_info *session_info);
 static
-struct session_info *session_info_create(const char *name,
-               uid_t uid, gid_t gid,
+struct session_info *session_info_create(uint64_t id,
+               const char *name,
+               uid_t uid,
+               gid_t gid,
                struct lttng_session_trigger_list *trigger_list,
                struct cds_lfht *sessions_ht);
-static
-void session_info_add_channel(struct session_info *session_info,
-               struct channel_info *channel_info);
+static void session_info_add_channel(
+               struct session_info *session_info, struct channel_info *channel_info);
 static
 void session_info_remove_channel(struct session_info *session_info,
                struct channel_info *channel_info);
@@ -322,13 +323,60 @@ int match_client_list_condition(struct cds_lfht_node *node, const void *key)
 }
 
 static
-int match_session(struct cds_lfht_node *node, const void *key)
+int match_session_info(struct cds_lfht_node *node, const void *key)
 {
-       const char *name = (const char *) key;
-       struct session_info *session_info = lttng::utils::container_of(
+       const auto session_id = *((uint64_t *) key);
+       const auto *session_info = lttng::utils::container_of(
                node, &session_info::sessions_ht_node);
 
-       return !strcmp(session_info->name, name);
+       return session_id == session_info->id;
+}
+
+static
+unsigned long hash_session_info_id(uint64_t id)
+{
+       return hash_key_u64(&id, lttng_ht_seed);
+}
+
+static
+unsigned long hash_session_info(const struct session_info *session_info)
+{
+       return hash_session_info_id(session_info->id);
+}
+
+static
+struct session_info *get_session_info_by_id(
+               const struct notification_thread_state *state, uint64_t id)
+{
+       struct cds_lfht_iter iter;
+       struct cds_lfht_node *node;
+       lttng::urcu::read_lock_guard read_lock_guard;
+
+       cds_lfht_lookup(state->sessions_ht,
+                       hash_session_info_id(id),
+                       match_session_info,
+                       &id,
+                       &iter);
+       node = cds_lfht_iter_get_node(&iter);
+
+       if (node) {
+               auto session_info = lttng::utils::container_of(node, &session_info::sessions_ht_node);
+
+               session_info_get(session_info);
+               return session_info;
+       }
+
+       return NULL;
+}
+
+static
+struct session_info *get_session_info_by_name(
+               const struct notification_thread_state *state, const char *name)
+{
+       uint64_t session_id;
+       const auto found = sample_session_id_by_name(name, &session_id);
+
+       return found ? get_session_info_by_id(state, session_id) : NULL;
 }
 
 static
@@ -344,6 +392,10 @@ const char *notification_command_type_str(
                return "ADD_CHANNEL";
        case NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL:
                return "REMOVE_CHANNEL";
+       case NOTIFICATION_COMMAND_TYPE_ADD_SESSION:
+               return "ADD_SESSION";
+       case NOTIFICATION_COMMAND_TYPE_REMOVE_SESSION:
+               return "REMOVE_SESSION";
        case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING:
                return "SESSION_ROTATION_ONGOING";
        case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED:
@@ -563,7 +615,10 @@ void session_info_put(struct session_info *session_info)
 }
 
 static
-struct session_info *session_info_create(const char *name, uid_t uid, gid_t gid,
+struct session_info *session_info_create(uint64_t id,
+               const char *name,
+               uid_t uid,
+               gid_t gid,
                struct lttng_session_trigger_list *trigger_list,
                struct cds_lfht *sessions_ht)
 {
@@ -575,6 +630,7 @@ struct session_info *session_info_create(const char *name, uid_t uid, gid_t gid,
        if (!session_info) {
                goto end;
        }
+
        lttng_ref_init(&session_info->ref, session_info_destroy);
 
        session_info->channel_infos_ht = cds_lfht_new(DEFAULT_HT_SIZE,
@@ -584,10 +640,12 @@ struct session_info *session_info_create(const char *name, uid_t uid, gid_t gid,
        }
 
        cds_lfht_node_init(&session_info->sessions_ht_node);
+       session_info->id = id;
        session_info->name = strdup(name);
        if (!session_info->name) {
                goto error;
        }
+
        session_info->uid = uid;
        session_info->gid = gid;
        session_info->trigger_list = trigger_list;
@@ -960,32 +1018,21 @@ int evaluate_session_condition_for_client(
                uid_t *session_uid, gid_t *session_gid)
 {
        int ret;
-       struct cds_lfht_iter iter;
-       struct cds_lfht_node *node;
        const char *session_name;
        struct session_info *session_info = NULL;
 
        rcu_read_lock();
        session_name = get_condition_session_name(condition);
 
-       /* Find the session associated with the trigger. */
-       cds_lfht_lookup(state->sessions_ht,
-                       hash_key_str(session_name, lttng_ht_seed),
-                       match_session,
-                       session_name,
-                       &iter);
-       node = cds_lfht_iter_get_node(&iter);
-       if (!node) {
-               DBG("No known session matching name \"%s\"",
+       /* Find the session associated with the condition. */
+       session_info = get_session_info_by_name(state, session_name);
+       if (!session_info) {
+               DBG("Unknown session while evaluating session condition for client: name = `%s`",
                                session_name);
                ret = 0;
                goto end;
        }
 
-       session_info = caa_container_of(node, struct session_info,
-                       sessions_ht_node);
-       session_info_get(session_info);
-
        /*
         * Evaluation is performed in-line here since only one type of
         * session-bound condition is handled for the moment.
@@ -1654,39 +1701,22 @@ error:
 }
 
 static
-struct session_info *find_or_create_session_info(
-               struct notification_thread_state *state,
-               const char *name, uid_t uid, gid_t gid)
+struct session_info *create_and_publish_session_info(struct notification_thread_state *state,
+               uint64_t id,
+               const char *name,
+               uid_t uid,
+               gid_t gid)
 {
        struct session_info *session = NULL;
-       struct cds_lfht_node *node;
-       struct cds_lfht_iter iter;
        struct lttng_session_trigger_list *trigger_list;
 
        rcu_read_lock();
-       cds_lfht_lookup(state->sessions_ht,
-                       hash_key_str(name, lttng_ht_seed),
-                       match_session,
-                       name,
-                       &iter);
-       node = cds_lfht_iter_get_node(&iter);
-       if (node) {
-               DBG("Found session info of session \"%s\" (uid = %i, gid = %i)",
-                               name, uid, gid);
-               session = caa_container_of(node, struct session_info,
-                               sessions_ht_node);
-               LTTNG_ASSERT(session->uid == uid);
-               LTTNG_ASSERT(session->gid == gid);
-               session_info_get(session);
-               goto end;
-       }
-
        trigger_list = lttng_session_trigger_list_build(state, name);
        if (!trigger_list) {
                goto error;
        }
 
-       session = session_info_create(name, uid, gid, trigger_list,
+       session = session_info_create(id, name, uid, gid, trigger_list,
                        state->sessions_ht);
        if (!session) {
                ERR("Failed to allocation session info for session \"%s\" (uid = %i, gid = %i)",
@@ -1694,11 +1724,16 @@ struct session_info *find_or_create_session_info(
                lttng_session_trigger_list_destroy(trigger_list);
                goto error;
        }
+
+       /* Transferred ownership to the new session. */
        trigger_list = NULL;
 
-       cds_lfht_add(state->sessions_ht, hash_key_str(name, lttng_ht_seed),
-                       &session->sessions_ht_node);
-end:
+       if (cds_lfht_add_unique(state->sessions_ht, hash_session_info(session), match_session_info,
+                           &id, &session->sessions_ht_node) != &session->sessions_ht_node) {
+               ERR("Duplicate session found: name = `%s`, id = %" PRIu64, name, id);
+               goto error;
+       }
+
        rcu_read_unlock();
        return session;
 error:
@@ -1708,11 +1743,12 @@ error:
 }
 
 static
-int handle_notification_thread_command_add_channel(
-               struct notification_thread_state *state,
-               const char *session_name, uid_t session_uid, gid_t session_gid,
-               const char *channel_name, enum lttng_domain_type channel_domain,
-               uint64_t channel_key_int, uint64_t channel_capacity,
+int handle_notification_thread_command_add_channel(struct notification_thread_state *state,
+               uint64_t session_id,
+               const char *channel_name,
+               enum lttng_domain_type channel_domain,
+               uint64_t channel_key_int,
+               uint64_t channel_capacity,
                enum lttng_error_code *cmd_result)
 {
        struct cds_list_head trigger_list;
@@ -1727,16 +1763,17 @@ int handle_notification_thread_command_add_channel(
        struct cds_lfht_iter iter;
        struct session_info *session_info = NULL;
 
-       DBG("Adding channel %s from session %s, channel key = %" PRIu64 " in %s domain",
-                       channel_name, session_name, channel_key_int,
+       DBG("Adding channel: channel name = `%s`, session id = %" PRIu64 ", channel key = %" PRIu64 ", domain = %s",
+                       channel_name, session_id, channel_key_int,
                        lttng_domain_type_str(channel_domain));
 
        CDS_INIT_LIST_HEAD(&trigger_list);
 
-       session_info = find_or_create_session_info(state, session_name,
-                       session_uid, session_gid);
+       session_info = get_session_info_by_id(state, session_id);
        if (!session_info) {
-               /* Allocation error or an internal error occurred. */
+               /* Fatal logic error. */
+               ERR("Failed to find session while adding channel: session id = %" PRIu64,
+                               session_id);
                goto error;
        }
 
@@ -1802,6 +1839,67 @@ error:
        return 1;
 }
 
+static
+int handle_notification_thread_command_add_session(struct notification_thread_state *state,
+               uint64_t session_id,
+               const char *session_name,
+               uid_t session_uid,
+               gid_t session_gid,
+               enum lttng_error_code *cmd_result)
+{
+       int ret;
+
+       DBG("Adding session: session name = `%s`, session id = %" PRIu64 ", session uid = %d, session gid = %d",
+                       session_name, session_id, session_uid, session_gid);
+
+       auto session = create_and_publish_session_info(state, session_id, session_name, session_uid, session_gid);
+       if (!session) {
+               PERROR("Failed to add session: session name = `%s`, session id = %" PRIu64 ", session uid = %d, session gid = %d",
+                               session_name, session_id, session_uid, session_gid);
+               ret = -1;
+               *cmd_result = LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       /*
+        * Note that the reference to `session` is not released; this reference is
+        * the "global" reference that is used to allow look-ups. This reference will
+        * only be released when the session is removed. See
+        * handle_notification_thread_command_remove_session.
+        */
+       ret = 0;
+       *cmd_result = LTTNG_OK;
+end:
+       return ret;
+}
+
+static
+int handle_notification_thread_command_remove_session(
+               struct notification_thread_state *state,
+               uint64_t session_id,
+               enum lttng_error_code *cmd_result)
+{
+       int ret;
+
+       DBG("Removing session: session id = %" PRIu64, session_id);
+
+       auto session = get_session_info_by_id(state, session_id);
+       if (!session) {
+               ERR("Failed to remove session: session id = %" PRIu64, session_id);
+               ret = -1;
+               *cmd_result = LTTNG_ERR_NO_SESSION;
+               goto end;
+       }
+
+       /* Release the reference returned by the look-up, and then release the global reference. */
+       session_info_put(session);
+       session_info_put(session);
+       ret = 0;
+       *cmd_result = LTTNG_OK;
+end:
+       return ret;
+}
+
 static
 void free_channel_trigger_list_rcu(struct rcu_head *node)
 {
@@ -1902,7 +2000,7 @@ static
 int handle_notification_thread_command_session_rotation(
        struct notification_thread_state *state,
        enum notification_thread_command_type cmd_type,
-       const char *session_name, uid_t session_uid, gid_t session_gid,
+       uint64_t session_id,
        uint64_t trace_archive_chunk_id,
        struct lttng_trace_archive_location *location,
        enum lttng_error_code *_cmd_result)
@@ -1912,29 +2010,32 @@ int handle_notification_thread_command_session_rotation(
        struct lttng_session_trigger_list *trigger_list;
        struct lttng_trigger_list_element *trigger_list_element;
        struct session_info *session_info;
-       const struct lttng_credentials session_creds = {
-               .uid = LTTNG_OPTIONAL_INIT_VALUE(session_uid),
-               .gid = LTTNG_OPTIONAL_INIT_VALUE(session_gid),
-       };
+       struct lttng_credentials session_creds;
 
        rcu_read_lock();
 
-       session_info = find_or_create_session_info(state, session_name,
-                       session_uid, session_gid);
+       session_info = get_session_info_by_id(state, session_id);
        if (!session_info) {
-               /* Allocation error or an internal error occurred. */
+               /* Fatal logic error. */
+               ERR("Failed to find session while handling rotation state change: session id = %" PRIu64,
+                               session_id);
                ret = -1;
-               cmd_result = LTTNG_ERR_NOMEM;
+               cmd_result = LTTNG_ERR_FATAL;
                goto end;
        }
 
+       session_creds = {
+               .uid = LTTNG_OPTIONAL_INIT_VALUE(session_info->uid),
+               .gid = LTTNG_OPTIONAL_INIT_VALUE(session_info->gid),
+       };
+
        session_info->rotation.ongoing =
                        cmd_type == NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING;
        session_info->rotation.id = trace_archive_chunk_id;
-       trigger_list = get_session_trigger_list(state, session_name);
+       trigger_list = get_session_trigger_list(state, session_info->name);
        if (!trigger_list) {
-               DBG("No triggers applying to session \"%s\" found",
-                               session_name);
+               DBG("No triggers apply to session: session name = `%s` ",
+                               session_info->name);
                goto end;
        }
 
@@ -3180,9 +3281,7 @@ int handle_notification_thread_command(
        case NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL:
                ret = handle_notification_thread_command_add_channel(
                                state,
-                               cmd->parameters.add_channel.session.name,
-                               cmd->parameters.add_channel.session.uid,
-                               cmd->parameters.add_channel.session.gid,
+                               cmd->parameters.add_channel.session.id,
                                cmd->parameters.add_channel.channel.name,
                                cmd->parameters.add_channel.channel.domain,
                                cmd->parameters.add_channel.channel.key,
@@ -3195,14 +3294,23 @@ int handle_notification_thread_command(
                                cmd->parameters.remove_channel.domain,
                                &cmd->reply_code);
                break;
+       case NOTIFICATION_COMMAND_TYPE_ADD_SESSION:
+               ret = handle_notification_thread_command_add_session(state,
+                               cmd->parameters.add_session.session_id,
+                               cmd->parameters.add_session.session_name,
+                               cmd->parameters.add_session.session_uid,
+                               cmd->parameters.add_session.session_gid, &cmd->reply_code);
+               break;
+       case NOTIFICATION_COMMAND_TYPE_REMOVE_SESSION:
+               ret = handle_notification_thread_command_remove_session(
+                               state, cmd->parameters.remove_session.session_id, &cmd->reply_code);
+               break;
        case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING:
        case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED:
                ret = handle_notification_thread_command_session_rotation(
                                state,
                                cmd->type,
-                               cmd->parameters.session_rotation.session_name,
-                               cmd->parameters.session_rotation.uid,
-                               cmd->parameters.session_rotation.gid,
+                               cmd->parameters.session_rotation.session_id,
                                cmd->parameters.session_rotation.trace_archive_chunk_id,
                                cmd->parameters.session_rotation.location,
                                &cmd->reply_code);
index 0c992073e31debd2b4e0db8b54995d0da3d87bdd..b53c24b2398a98f77de8534d210b72677eb250de 100644 (file)
@@ -30,6 +30,7 @@ struct channel_key {
 
 struct session_info {
        struct lttng_ref ref;
+       uint64_t id;
        char *name;
        uid_t uid;
        gid_t gid;
index 2f77189ad143c7763e9a7ee4fc76280d64d7db2a..2ff86dc0613a04fb3e4e75618516c07fb83a9ccb 100644 (file)
@@ -157,13 +157,15 @@ struct notification_thread_handle {
  * The thread reacts to the following internal events:
  *   1) creation of a tracing channel,
  *   2) destruction of a tracing channel,
- *   3) registration of a trigger,
- *   4) unregistration of a trigger,
- *   5) reception of a channel monitor sample from the consumer daemon,
- *   6) Session rotation ongoing,
- *   7) Session rotation completed,
- *   8) registration of a tracer event source,
- *   9) unregistration of a tracer event source,
+ *   3) creation of a tracing session,
+ *   4) destruction of a tracing session,
+ *   5)  registration of a trigger,
+ *   6)  unregistration of a trigger,
+ *   7)  reception of a channel monitor sample from the consumer daemon,
+ *   8)  Session rotation ongoing,
+ *   9)  Session rotation completed,
+ *   10) registration of a tracer event source,
+ *   11) unregistration of a tracer event source,
  *
  * Events specific to notification-emitting triggers:
  *   9) connection of a notification client,
index c1c6c50debb4953c0f6c757cf9daa2cee51a9419..5efc24edda31b81af320718c4f05bcbd2f5774e2 100644 (file)
@@ -487,9 +487,7 @@ int check_session_rotation_pending(struct ltt_session *session,
                location = session_get_trace_archive_location(session);
                ret = notification_thread_command_session_rotation_completed(
                                notification_thread_handle,
-                               session->name,
-                               session->uid,
-                               session->gid,
+                               session->id,
                                session->last_archived_chunk_id.value,
                                location);
                lttng_trace_archive_location_put(location);
index 1cfb08f917e4ce304fdaeef705d50ee95b73b7ce..c80658cbbe512a2b5031b69e51cf339806c2240d 100644 (file)
@@ -3461,11 +3461,7 @@ static int create_channel_per_uid(struct ust_app *app,
 
        /* 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(
-                                       &ua_sess->effective_credentials),
-                       lttng_credentials_get_gid(
-                                       &ua_sess->effective_credentials),
+                       the_notification_thread_handle, session->id,
                        ua_chan->name, ua_chan->key, LTTNG_DOMAIN_UST,
                        ua_chan->attr.subbuf_size * ua_chan->attr.num_subbuf);
        if (notification_ret != LTTNG_OK) {
@@ -3563,11 +3559,7 @@ static int create_channel_per_pid(struct ust_app *app,
        }
 
        cmd_ret = notification_thread_command_add_channel(
-                       the_notification_thread_handle, session->name,
-                       lttng_credentials_get_uid(
-                                       &ua_sess->effective_credentials),
-                       lttng_credentials_get_gid(
-                                       &ua_sess->effective_credentials),
+                       the_notification_thread_handle, session->id,
                        ua_chan->name, ua_chan->key, LTTNG_DOMAIN_UST,
                        ua_chan->attr.subbuf_size * ua_chan->attr.num_subbuf);
        if (cmd_ret != LTTNG_OK) {
This page took 0.038938 seconds and 4 git commands to generate.