Fix: skip uid registry when metadata key is 0
[lttng-tools.git] / src / bin / lttng-sessiond / ust-app.c
index d292779d156dca47d2ce1d861ac35d216811d731..52d1da787f8142cd7cf92bab17acd9d3eda11235 100644 (file)
@@ -43,6 +43,7 @@
 #include "session.h"
 #include "lttng-sessiond.h"
 #include "notification-thread-commands.h"
+#include "rotate.h"
 
 static
 int ust_app_flush_app_session(struct ust_app *app, struct ust_app_session *ua_sess);
@@ -92,6 +93,7 @@ static void copy_channel_attr_to_ustctl(
        attr->switch_timer_interval = uattr->switch_timer_interval;
        attr->read_timer_interval = uattr->read_timer_interval;
        attr->output = uattr->output;
+       attr->blocking_timeout = uattr->u.s.blocking_timeout;
 }
 
 /*
@@ -813,6 +815,7 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess,
        ua_sess->deleted = true;
 
        registry = get_session_registry(ua_sess);
+       /* Registry can be null on error path during initialization. */
        if (registry) {
                /* Push metadata for application before freeing the application. */
                (void) push_metadata(registry, ua_sess->consumer);
@@ -840,6 +843,10 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess,
        if (ua_sess->buffer_type == LTTNG_BUFFER_PER_PID) {
                struct buffer_reg_pid *reg_pid = buffer_reg_pid_find(ua_sess->id);
                if (reg_pid) {
+                       /*
+                        * Registry can be null on error path during
+                        * initialization.
+                        */
                        buffer_reg_pid_remove(reg_pid);
                        buffer_reg_pid_destroy(reg_pid);
                }
@@ -972,7 +979,7 @@ end:
  * Alloc new UST app session.
  */
 static
-struct ust_app_session *alloc_ust_app_session(struct ust_app *app)
+struct ust_app_session *alloc_ust_app_session(void)
 {
        struct ust_app_session *ua_sess;
 
@@ -1035,6 +1042,7 @@ struct ust_app_channel *alloc_ust_app_channel(char *name,
                ua_chan->attr.switch_timer_interval = attr->switch_timer_interval;
                ua_chan->attr.read_timer_interval = attr->read_timer_interval;
                ua_chan->attr.output = attr->output;
+               ua_chan->attr.blocking_timeout = attr->u.s.blocking_timeout;
        }
        /* By default, the channel is a per cpu channel. */
        ua_chan->attr.type = LTTNG_UST_CHAN_PER_CPU;
@@ -1798,6 +1806,8 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan,
        ua_chan->attr.read_timer_interval = uchan->attr.read_timer_interval;
        ua_chan->monitor_timer_interval = uchan->monitor_timer_interval;
        ua_chan->attr.output = uchan->attr.output;
+       ua_chan->attr.blocking_timeout = uchan->attr.u.s.blocking_timeout;
+
        /*
         * Note that the attribute channel type is not set since the channel on the
         * tracing registry side does not have this information.
@@ -2144,7 +2154,7 @@ error:
  * Returns 0 on success or else a negative code which is either -ENOMEM or
  * -ENOTCONN which is the default code if the ustctl_create_session fails.
  */
-static int create_ust_app_session(struct ltt_ust_session *usess,
+static int find_or_create_ust_app_session(struct ltt_ust_session *usess,
                struct ust_app *app, struct ust_app_session **ua_sess_ptr,
                int *is_created)
 {
@@ -2161,7 +2171,7 @@ static int create_ust_app_session(struct ltt_ust_session *usess,
        if (ua_sess == NULL) {
                DBG2("UST app pid: %d session id %" PRIu64 " not found, creating it",
                                app->pid, usess->id);
-               ua_sess = alloc_ust_app_session(app);
+               ua_sess = alloc_ust_app_session();
                if (ua_sess == NULL) {
                        /* Only malloc can failed so something is really wrong */
                        ret = -ENOMEM;
@@ -2337,8 +2347,7 @@ end:
  * Called with UST app session lock held and a RCU read side lock.
  */
 static
-int create_ust_app_channel_context(struct ust_app_session *ua_sess,
-               struct ust_app_channel *ua_chan,
+int create_ust_app_channel_context(struct ust_app_channel *ua_chan,
                struct lttng_ust_context_attr *uctx,
                struct ust_app *app)
 {
@@ -2356,7 +2365,7 @@ int create_ust_app_channel_context(struct ust_app_session *ua_sess,
        ua_ctx = alloc_ust_app_ctx(uctx);
        if (ua_ctx == NULL) {
                /* malloc failed */
-               ret = -1;
+               ret = -ENOMEM;
                goto error;
        }
 
@@ -2468,11 +2477,14 @@ error:
 /*
  * Ask the consumer to create a channel and get it if successful.
  *
+ * Called with UST app session lock held.
+ *
  * Return 0 on success or else a negative value.
  */
 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, struct ust_registry_session *registry)
+               int bitness, struct ust_registry_session *registry,
+               uint64_t trace_archive_id)
 {
        int ret;
        unsigned int nb_fd = 0;
@@ -2507,7 +2519,7 @@ static int do_consumer_create_channel(struct ltt_ust_session *usess,
         * stream we have to expect.
         */
        ret = ust_consumer_ask_channel(ua_sess, ua_chan, usess->consumer, socket,
-                       registry);
+                       registry, trace_archive_id);
        if (ret < 0) {
                goto error_ask;
        }
@@ -2834,6 +2846,9 @@ error:
 /*
  * Create and send to the application the created buffers with per UID buffers.
  *
+ * This MUST be called with a RCU read side lock acquired.
+ * The session list lock and the session's lock must be acquired.
+ *
  * Return 0 on success else a negative value.
  */
 static int create_channel_per_uid(struct ust_app *app,
@@ -2843,7 +2858,9 @@ static int create_channel_per_uid(struct ust_app *app,
        int ret;
        struct buffer_reg_uid *reg_uid;
        struct buffer_reg_channel *reg_chan;
-       bool created = false;
+       struct ltt_session *session;
+       enum lttng_error_code notification_ret;
+       struct ust_registry_channel *chan_reg;
 
        assert(app);
        assert(usess);
@@ -2862,92 +2879,85 @@ static int create_channel_per_uid(struct ust_app *app,
 
        reg_chan = buffer_reg_channel_find(ua_chan->tracing_channel_id,
                        reg_uid);
-       if (!reg_chan) {
-               /* Create the buffer registry channel object. */
-               ret = create_buffer_reg_channel(reg_uid->registry, ua_chan, &reg_chan);
-               if (ret < 0) {
-                       ERR("Error creating the UST channel \"%s\" registry instance",
-                               ua_chan->name);
-                       goto error;
-               }
-               assert(reg_chan);
+       if (reg_chan) {
+               goto send_channel;
+       }
 
-               /*
-                * Create the buffers on the consumer side. This call populates the
-                * 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);
-               if (ret < 0) {
-                       ERR("Error creating UST channel \"%s\" on the consumer daemon",
+       /* Create the buffer registry channel object. */
+       ret = create_buffer_reg_channel(reg_uid->registry, ua_chan, &reg_chan);
+       if (ret < 0) {
+               ERR("Error creating the UST channel \"%s\" registry instance",
                                ua_chan->name);
+               goto error;
+       }
 
-                       /*
-                        * 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);
-                       buffer_reg_channel_remove(reg_uid->registry, reg_chan);
-                       buffer_reg_channel_destroy(reg_chan, LTTNG_DOMAIN_UST);
-                       goto error;
-               }
+       session = session_find_by_id(ua_sess->tracing_id);
+       assert(session);
+       assert(pthread_mutex_trylock(&session->lock));
+       assert(session_trylock_list());
+
+       /*
+        * Create the buffers on the consumer side. This call populates the
+        * 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,
+                       session->current_archive_id);
+       if (ret < 0) {
+               ERR("Error creating UST channel \"%s\" on the consumer daemon",
+                               ua_chan->name);
 
                /*
-                * Setup the streams and add it to the session registry.
+                * Let's remove the previously created buffer registry channel so
+                * it's not visible anymore in the session registry.
                 */
-               ret = setup_buffer_reg_channel(reg_uid->registry,
-                               ua_chan, reg_chan, app);
-               if (ret < 0) {
-                       ERR("Error setting up UST channel \"%s\"",
-                               ua_chan->name);
-                       goto error;
-               }
-               created = true;
+               ust_registry_channel_del_free(reg_uid->registry->reg.ust,
+                               ua_chan->tracing_channel_id, false);
+               buffer_reg_channel_remove(reg_uid->registry, reg_chan);
+               buffer_reg_channel_destroy(reg_chan, LTTNG_DOMAIN_UST);
+               goto error;
        }
 
-       /* Send buffers to the application. */
-       ret = send_channel_uid_to_ust(reg_chan, app, ua_sess, ua_chan);
+       /*
+        * Setup the streams and add it to the session registry.
+        */
+       ret = setup_buffer_reg_channel(reg_uid->registry,
+                       ua_chan, reg_chan, app);
        if (ret < 0) {
-               if (ret != -ENOTCONN) {
-                       ERR("Error sending channel to application");
-               }
+               ERR("Error setting up UST channel \"%s\"", ua_chan->name);
                goto error;
        }
 
-       if (created) {
-               enum lttng_error_code cmd_ret;
-               struct ltt_session *session;
-               uint64_t chan_reg_key;
-               struct ust_registry_channel *chan_reg;
+       /* Notify the notification subsystem of the channel's creation. */
+       pthread_mutex_lock(&reg_uid->registry->reg.ust->lock);
+       chan_reg = ust_registry_channel_find(reg_uid->registry->reg.ust,
+                       ua_chan->tracing_channel_id);
+       assert(chan_reg);
+       chan_reg->consumer_key = ua_chan->key;
+       chan_reg = NULL;
+       pthread_mutex_unlock(&reg_uid->registry->reg.ust->lock);
 
-               rcu_read_lock();
-               chan_reg_key = ua_chan->tracing_channel_id;
+       notification_ret = notification_thread_command_add_channel(
+                       notification_thread_handle, session->name,
+                       ua_sess->euid, ua_sess->egid,
+                       ua_chan->name,
+                       ua_chan->key,
+                       LTTNG_DOMAIN_UST,
+                       ua_chan->attr.subbuf_size * ua_chan->attr.num_subbuf);
+       if (notification_ret != LTTNG_OK) {
+               ret = - (int) notification_ret;
+               ERR("Failed to add channel to notification thread");
+               goto error;
+       }
 
-               pthread_mutex_lock(&reg_uid->registry->reg.ust->lock);
-               chan_reg = ust_registry_channel_find(reg_uid->registry->reg.ust,
-                               chan_reg_key);
-               assert(chan_reg);
-               chan_reg->consumer_key = ua_chan->key;
-               chan_reg = NULL;
-               pthread_mutex_unlock(&reg_uid->registry->reg.ust->lock);
-
-               session = session_find_by_id(ua_sess->tracing_id);
-               assert(session);
-
-               cmd_ret = notification_thread_command_add_channel(
-                               notification_thread_handle, session->name,
-                               ua_sess->euid, ua_sess->egid,
-                               ua_chan->name,
-                               ua_chan->key,
-                               LTTNG_DOMAIN_UST,
-                               ua_chan->attr.subbuf_size * ua_chan->attr.num_subbuf);
-               rcu_read_unlock();
-               if (cmd_ret != LTTNG_OK) {
-                       ret = - (int) cmd_ret;
-                       ERR("Failed to add channel to notification thread");
-                       goto error;
+send_channel:
+       /* Send buffers to the application. */
+       ret = send_channel_uid_to_ust(reg_chan, app, ua_sess, ua_chan);
+       if (ret < 0) {
+               if (ret != -ENOTCONN) {
+                       ERR("Error sending channel to application");
                }
+               goto error;
        }
 
 error:
@@ -2957,6 +2967,9 @@ error:
 /*
  * Create and send to the application the created buffers with per PID buffers.
  *
+ * Called with UST app session lock held.
+ * The session list lock and the session's lock must be acquired.
+ *
  * Return 0 on success else a negative value.
  */
 static int create_channel_per_pid(struct ust_app *app,
@@ -2980,6 +2993,7 @@ static int create_channel_per_pid(struct ust_app *app,
        rcu_read_lock();
 
        registry = get_session_registry(ua_sess);
+       /* The UST app session lock is held, registry shall not be null. */
        assert(registry);
 
        /* Create and add a new channel registry to session. */
@@ -2990,9 +3004,16 @@ static int create_channel_per_pid(struct ust_app *app,
                goto error;
        }
 
+       session = session_find_by_id(ua_sess->tracing_id);
+       assert(session);
+
+       assert(pthread_mutex_trylock(&session->lock));
+       assert(session_trylock_list());
+
        /* Create and get channel on the consumer side. */
        ret = do_consumer_create_channel(usess, ua_sess, ua_chan,
-                       app->bits_per_long, registry);
+                       app->bits_per_long, registry,
+                       session->current_archive_id);
        if (ret < 0) {
                ERR("Error creating UST channel \"%s\" on the consumer daemon",
                        ua_chan->name);
@@ -3007,9 +3028,6 @@ static int create_channel_per_pid(struct ust_app *app,
                goto error;
        }
 
-       session = session_find_by_id(ua_sess->tracing_id);
-       assert(session);
-
        chan_reg_key = ua_chan->key;
        pthread_mutex_lock(&registry->lock);
        chan_reg = ust_registry_channel_find(registry, chan_reg_key);
@@ -3040,6 +3058,8 @@ error:
  * need and send it to the application. This MUST be called with a RCU read
  * side lock acquired.
  *
+ * Called with UST app session lock held.
+ *
  * Return 0 on success or else a negative value. Returns -ENOTCONN if
  * the application exited concurrently.
  */
@@ -3220,12 +3240,14 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
        struct ust_app_channel *metadata;
        struct consumer_socket *socket;
        struct ust_registry_session *registry;
+       struct ltt_session *session;
 
        assert(ua_sess);
        assert(app);
        assert(consumer);
 
        registry = get_session_registry(ua_sess);
+       /* The UST app session is held registry shall not be null. */
        assert(registry);
 
        pthread_mutex_lock(&registry->lock);
@@ -3268,6 +3290,12 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
         */
        registry->metadata_key = metadata->key;
 
+       session = session_find_by_id(ua_sess->tracing_id);
+       assert(session);
+
+       assert(pthread_mutex_trylock(&session->lock));
+       assert(session_trylock_list());
+
        /*
         * Ask the metadata channel creation to the consumer. The metadata object
         * will be created by the consumer and kept their. However, the stream is
@@ -3275,7 +3303,7 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
         * consumer.
         */
        ret = ust_consumer_ask_channel(ua_sess, metadata, consumer, socket,
-                       registry);
+                       registry, session->current_archive_id);
        if (ret < 0) {
                /* Nullify the metadata key so we don't try to close it later on. */
                registry->metadata_key = 0;
@@ -3560,8 +3588,8 @@ void ust_app_unregister(int sock)
        /*
         * Remove application from notify hash table. The thread handling the
         * notify socket could have deleted the node so ignore on error because
-        * either way it's valid. The close of that socket is handled by the other
-        * thread.
+        * either way it's valid. The close of that socket is handled by the
+        * apps_notify_thread.
         */
        iter.iter.node = &lta->notify_sock_n.node;
        (void) lttng_ht_del(ust_app_ht_by_notify_sock, &iter);
@@ -4147,7 +4175,7 @@ int ust_app_create_channel_glb(struct ltt_ust_session *usess,
                 * that if session exist, it will simply return a pointer to the ust
                 * app session.
                 */
-               ret = create_ust_app_session(usess, app, &ua_sess, &created);
+               ret = find_or_create_ust_app_session(usess, app, &ua_sess, &created);
                if (ret < 0) {
                        switch (ret) {
                        case -ENOTCONN:
@@ -4362,6 +4390,9 @@ int ust_app_create_event_glb(struct ltt_ust_session *usess,
 
 /*
  * Start tracing for a specific UST session and app.
+ *
+ * Called with UST app session lock held.
+ *
  */
 static
 int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
@@ -4397,9 +4428,33 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
 
        /* Create directories if consumer is LOCAL and has a path defined. */
        if (usess->consumer->type == CONSUMER_DST_LOCAL &&
-                       strlen(usess->consumer->dst.trace_path) > 0) {
-               ret = run_as_mkdir_recursive(usess->consumer->dst.trace_path,
-                               S_IRWXU | S_IRWXG, ua_sess->euid, ua_sess->egid);
+                       usess->consumer->dst.session_root_path[0] != '\0') {
+               char *tmp_path;
+
+               tmp_path = zmalloc(LTTNG_PATH_MAX);
+               if (!tmp_path) {
+                       ERR("Alloc tmp_path");
+                       goto error_unlock;
+               }
+               ret = snprintf(tmp_path, LTTNG_PATH_MAX, "%s%s%s",
+                               usess->consumer->dst.session_root_path,
+                               usess->consumer->chunk_path,
+                               usess->consumer->subdir);
+               if (ret >= LTTNG_PATH_MAX) {
+                       ERR("Local destination path exceeds the maximal allowed length of %i bytes (needs %i bytes) with path = \"%s%s%s\"",
+                                       LTTNG_PATH_MAX, ret,
+                                       usess->consumer->dst.session_root_path,
+                                       usess->consumer->chunk_path,
+                                       usess->consumer->subdir);
+                       free(tmp_path);
+                       goto error_unlock;
+               }
+
+               DBG("Creating directory path for local tracing: \"%s\"",
+                               tmp_path);
+               ret = run_as_mkdir_recursive(tmp_path, S_IRWXU | S_IRWXG,
+                               ua_sess->euid, ua_sess->egid);
+               free(tmp_path);
                if (ret < 0) {
                        if (errno != EEXIST) {
                                ERR("Trace directory creation error");
@@ -4545,6 +4600,8 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app)
        health_code_update();
 
        registry = get_session_registry(ua_sess);
+
+       /* The UST app session is held registry shall not be null. */
        assert(registry);
 
        /* Push metadata for application before freeing the application. */
@@ -4995,7 +5052,7 @@ void ust_app_global_create(struct ltt_ust_session *usess, struct ust_app *app)
        struct ust_app_ctx *ua_ctx;
        int is_created = 0;
 
-       ret = create_ust_app_session(usess, app, &ua_sess, &is_created);
+       ret = find_or_create_ust_app_session(usess, app, &ua_sess, &is_created);
        if (ret < 0) {
                /* Tracer is probably gone or ENOMEM. */
                goto error;
@@ -5172,7 +5229,7 @@ int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess,
                }
                ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel,
                                node);
-               ret = create_ust_app_channel_context(ua_sess, ua_chan, &uctx->ctx, app);
+               ret = create_ust_app_channel_context(ua_chan, &uctx->ctx, app);
                if (ret < 0) {
                        goto next_app;
                }
@@ -5368,7 +5425,7 @@ error:
  *
  * On success 0 is returned else a negative value.
  */
-static int reply_ust_register_channel(int sock, int sobjd, int cobjd,
+static int reply_ust_register_channel(int sock, int cobjd,
                size_t nr_fields, struct ustctl_field *fields)
 {
        int ret, ret_code = 0;
@@ -5386,19 +5443,17 @@ static int reply_ust_register_channel(int sock, int sobjd, int cobjd,
        /* 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 teardown. Abort event notify",
+               DBG("Application socket %d is being torn down. Abort event notify",
                                sock);
                ret = 0;
-               free(fields);
                goto error_rcu_unlock;
        }
 
        /* Lookup channel by UST object descriptor. */
        ua_chan = find_channel_by_objd(app, cobjd);
        if (!ua_chan) {
-               DBG("Application channel is being teardown. Abort event notify");
+               DBG("Application channel is being torn down. Abort event notify");
                ret = 0;
-               free(fields);
                goto error_rcu_unlock;
        }
 
@@ -5407,7 +5462,11 @@ static int reply_ust_register_channel(int sock, int sobjd, int cobjd,
 
        /* Get right session registry depending on the session buffer type. */
        registry = get_session_registry(ua_sess);
-       assert(registry);
+       if (!registry) {
+               DBG("Application session is being torn down. Abort event notify");
+               ret = 0;
+               goto error_rcu_unlock;
+       };
 
        /* Depending on the buffer type, a different channel key is used. */
        if (ua_sess->buffer_type == LTTNG_BUFFER_PER_UID) {
@@ -5431,13 +5490,11 @@ static int reply_ust_register_channel(int sock, int sobjd, int cobjd,
 
                chan_reg->nr_ctx_fields = nr_fields;
                chan_reg->ctx_fields = fields;
+               fields = NULL;
                chan_reg->header_type = type;
        } else {
                /* Get current already assigned values. */
                type = chan_reg->header_type;
-               free(fields);
-               /* Set to NULL so the error path does not do a double free. */
-               fields = NULL;
        }
        /* Channel id is set during the object creation. */
        chan_id = chan_reg->chan_id;
@@ -5473,9 +5530,7 @@ error:
        pthread_mutex_unlock(&registry->lock);
 error_rcu_unlock:
        rcu_read_unlock();
-       if (ret) {
-               free(fields);
-       }
+       free(fields);
        return ret;
 }
 
@@ -5505,23 +5560,17 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name,
        /* 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 teardown. Abort event notify",
+               DBG("Application socket %d is being torn down. Abort event notify",
                                sock);
                ret = 0;
-               free(sig);
-               free(fields);
-               free(model_emf_uri);
                goto error_rcu_unlock;
        }
 
        /* Lookup channel by UST object descriptor. */
        ua_chan = find_channel_by_objd(app, cobjd);
        if (!ua_chan) {
-               DBG("Application channel is being teardown. Abort event notify");
+               DBG("Application channel is being torn down. Abort event notify");
                ret = 0;
-               free(sig);
-               free(fields);
-               free(model_emf_uri);
                goto error_rcu_unlock;
        }
 
@@ -5529,7 +5578,11 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name,
        ua_sess = ua_chan->session;
 
        registry = get_session_registry(ua_sess);
-       assert(registry);
+       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;
@@ -5548,6 +5601,9 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name,
                        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;
 
        /*
         * The return value is returned to ustctl so in case of an error, the
@@ -5575,6 +5631,9 @@ error:
        pthread_mutex_unlock(&registry->lock);
 error_rcu_unlock:
        rcu_read_unlock();
+       free(sig);
+       free(fields);
+       free(model_emf_uri);
        return ret;
 }
 
@@ -5611,13 +5670,17 @@ static int add_enum_ust_registry(int sock, int sobjd, char *name,
        ua_sess = find_session_by_objd(app, sobjd);
        if (!ua_sess) {
                /* Return an error since this is not an error */
-               DBG("Application session is being torn down. Aborting enum registration.");
+               DBG("Application session is being torn down (session not found). Aborting enum registration.");
                free(entries);
                goto error_rcu_unlock;
        }
 
        registry = get_session_registry(ua_sess);
-       assert(registry);
+       if (!registry) {
+               DBG("Application session is being torn down (registry not found). Aborting enum registration.");
+               free(entries);
+               goto error_rcu_unlock;
+       }
 
        pthread_mutex_lock(&registry->lock);
 
@@ -5740,7 +5803,7 @@ int ust_app_recv_notify(int sock)
                 * that if needed it will be freed. After this, it's invalid to access
                 * fields or clean it up.
                 */
-               ret = reply_ust_register_channel(sock, sobjd, cobjd, nr_fields,
+               ret = reply_ust_register_channel(sock, cobjd, nr_fields,
                                fields);
                if (ret < 0) {
                        goto error;
@@ -5889,12 +5952,20 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess,
        struct lttng_ht_iter iter;
        struct ust_app *app;
        char pathname[PATH_MAX];
+       struct ltt_session *session;
+       uint64_t trace_archive_id;
 
        assert(usess);
        assert(output);
 
        rcu_read_lock();
 
+       session = session_find_by_id(usess->id);
+       assert(session);
+       assert(pthread_mutex_trylock(&session->lock));
+       assert(session_trylock_list());
+       trace_archive_id = session->current_archive_id;
+
        switch (usess->buffer_type) {
        case LTTNG_BUFFER_PER_UID:
        {
@@ -5904,6 +5975,11 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess,
                        struct buffer_reg_channel *reg_chan;
                        struct consumer_socket *socket;
 
+                       if (!reg->registry->reg.ust->metadata_key) {
+                               /* Skip since no metadata is present */
+                               continue;
+                       }
+
                        /* Get consumer socket to use to push the metadata.*/
                        socket = consumer_find_socket_by_bitness(reg->bits_per_long,
                                        usess->consumer);
@@ -5924,16 +6000,20 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess,
                        /* Add the UST default trace dir to path. */
                        cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
                                        reg_chan, node.node) {
-                               ret = consumer_snapshot_channel(socket, reg_chan->consumer_key,
-                                               output, 0, usess->uid, usess->gid, pathname, wait,
-                                               nb_packets_per_stream);
+                               ret = consumer_snapshot_channel(socket,
+                                               reg_chan->consumer_key,
+                                               output, 0, usess->uid,
+                                               usess->gid, pathname, wait,
+                                               nb_packets_per_stream,
+                                               trace_archive_id);
                                if (ret < 0) {
                                        goto error;
                                }
                        }
                        ret = consumer_snapshot_channel(socket,
                                        reg->registry->reg.ust->metadata_key, output, 1,
-                                       usess->uid, usess->gid, pathname, wait, 0);
+                                       usess->uid, usess->gid, pathname, wait, 0,
+                                       trace_archive_id);
                        if (ret < 0) {
                                goto error;
                        }
@@ -5974,18 +6054,28 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess,
 
                        cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter,
                                        ua_chan, node.node) {
-                               ret = consumer_snapshot_channel(socket, ua_chan->key, output,
-                                               0, ua_sess->euid, ua_sess->egid, pathname, wait,
-                                               nb_packets_per_stream);
+                               ret = consumer_snapshot_channel(socket,
+                                               ua_chan->key, output,
+                                               0, ua_sess->euid, ua_sess->egid,
+                                               pathname, wait,
+                                               nb_packets_per_stream,
+                                               trace_archive_id);
                                if (ret < 0) {
                                        goto error;
                                }
                        }
 
                        registry = get_session_registry(ua_sess);
-                       assert(registry);
-                       ret = consumer_snapshot_channel(socket, registry->metadata_key, output,
-                                       1, ua_sess->euid, ua_sess->egid, pathname, wait, 0);
+                       if (!registry) {
+                               DBG("Application session is being torn down. Abort snapshot record.");
+                               ret = -1;
+                               goto error;
+                       }
+                       ret = consumer_snapshot_channel(socket,
+                                       registry->metadata_key, output,
+                                       1, ua_sess->euid, ua_sess->egid,
+                                       pathname, wait, 0,
+                                       trace_archive_id);
                        if (ret < 0) {
                                goto error;
                        }
@@ -6083,21 +6173,23 @@ int ust_app_uid_get_channel_runtime_stats(uint64_t ust_session_id,
        int ret;
        uint64_t consumer_chan_key;
 
+       *discarded = 0;
+       *lost = 0;
+
        ret = buffer_reg_uid_consumer_channel_key(
-                       buffer_reg_uid_list, ust_session_id,
-                       uchan_id, &consumer_chan_key);
+                       buffer_reg_uid_list, uchan_id, &consumer_chan_key);
        if (ret < 0) {
+               /* Not found */
+               ret = 0;
                goto end;
        }
 
        if (overwrite) {
                ret = consumer_get_lost_packets(ust_session_id,
                                consumer_chan_key, consumer, lost);
-               *discarded = 0;
        } else {
                ret = consumer_get_discarded_events(ust_session_id,
                                consumer_chan_key, consumer, discarded);
-               *lost = 0;
        }
 
 end:
@@ -6116,10 +6208,13 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
        struct ust_app_session *ua_sess;
        struct ust_app_channel *ua_chan;
 
+       *discarded = 0;
+       *lost = 0;
+
        rcu_read_lock();
        /*
-        * Iterate over every registered applications, return when we
-        * found one in the right session and channel.
+        * Iterate over every registered applications. Sum counters for
+        * all applications containing requested session and channel.
         */
        cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                struct lttng_ht_iter uiter;
@@ -6138,19 +6233,26 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
                ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
 
                if (overwrite) {
+                       uint64_t _lost;
+
                        ret = consumer_get_lost_packets(usess->id, ua_chan->key,
-                                       consumer, lost);
-                       *discarded = 0;
-                       goto end;
+                                       consumer, &_lost);
+                       if (ret < 0) {
+                               break;
+                       }
+                       (*lost) += _lost;
                } else {
+                       uint64_t _discarded;
+
                        ret = consumer_get_discarded_events(usess->id,
-                                       ua_chan->key, consumer, discarded);
-                       *lost = 0;
-                       goto end;
+                                       ua_chan->key, consumer, &_discarded);
+                       if (ret < 0) {
+                               break;
+                       }
+                       (*discarded) += _discarded;
                }
        }
 
-end:
        rcu_read_unlock();
        return ret;
 }
@@ -6220,3 +6322,203 @@ int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess)
 
        return 0;
 }
+
+/*
+ * Rotate all the channels of a session.
+ *
+ * Return 0 on success or else a negative value.
+ */
+int ust_app_rotate_session(struct ltt_session *session, bool *ust_active)
+{
+       int ret = 0;
+       struct lttng_ht_iter iter;
+       struct ust_app *app;
+       struct ltt_ust_session *usess = session->ust_session;
+       char pathname[LTTNG_PATH_MAX];
+
+       assert(usess);
+
+       rcu_read_lock();
+
+       switch (usess->buffer_type) {
+       case LTTNG_BUFFER_PER_UID:
+       {
+               struct buffer_reg_uid *reg;
+
+               cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
+                       struct buffer_reg_channel *reg_chan;
+                       struct consumer_socket *socket;
+
+                       /* Get consumer socket to use to push the metadata.*/
+                       socket = consumer_find_socket_by_bitness(reg->bits_per_long,
+                                       usess->consumer);
+                       if (!socket) {
+                               ret = -EINVAL;
+                               goto error;
+                       }
+
+                       /*
+                        * Account the metadata channel first to make sure the
+                        * number of channels waiting for a rotation cannot
+                        * reach 0 before we complete the iteration over all
+                        * the channels.
+                        */
+                       ret = rotate_add_channel_pending(
+                                       reg->registry->reg.ust->metadata_key,
+                                       LTTNG_DOMAIN_UST, session);
+                       if (ret < 0) {
+                               ret = reg->bits_per_long == 32 ?
+                                               -LTTNG_ERR_UST_CONSUMER32_FAIL :
+                                               -LTTNG_ERR_UST_CONSUMER64_FAIL;
+                               goto error;
+                       }
+
+                       ret = snprintf(pathname, sizeof(pathname),
+                                       DEFAULT_UST_TRACE_DIR "/" DEFAULT_UST_TRACE_UID_PATH,
+                                       reg->uid, reg->bits_per_long);
+                       if (ret < 0 || ret == sizeof(pathname)) {
+                               PERROR("Failed to format rotation path");
+                               goto error;
+                       }
+
+                       /* Rotate the data channels. */
+                       cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
+                                       reg_chan, node.node) {
+                               ret = rotate_add_channel_pending(
+                                               reg_chan->consumer_key,
+                                               LTTNG_DOMAIN_UST, session);
+                               if (ret < 0) {
+                                       ret = reg->bits_per_long == 32 ?
+                                                       -LTTNG_ERR_UST_CONSUMER32_FAIL :
+                                                       -LTTNG_ERR_UST_CONSUMER64_FAIL;
+                                       goto error;
+                               }
+                               ret = consumer_rotate_channel(socket,
+                                               reg_chan->consumer_key,
+                                               usess->uid, usess->gid,
+                                               usess->consumer, pathname,
+                                               /* is_metadata_channel */ false,
+                                               session->current_archive_id,
+                                               &session->rotate_pending_relay);
+                               if (ret < 0) {
+                                       goto error;
+                               }
+                       }
+
+                       (void) push_metadata(reg->registry->reg.ust, usess->consumer);
+
+                       ret = consumer_rotate_channel(socket,
+                                       reg->registry->reg.ust->metadata_key,
+                                       usess->uid, usess->gid,
+                                       usess->consumer, pathname,
+                                       /* is_metadata_channel */ true,
+                                       session->current_archive_id,
+                                       &session->rotate_pending_relay);
+                       if (ret < 0) {
+                               goto error;
+                       }
+                       *ust_active = true;
+               }
+               break;
+       }
+       case LTTNG_BUFFER_PER_PID:
+       {
+               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       struct consumer_socket *socket;
+                       struct lttng_ht_iter chan_iter;
+                       struct ust_app_channel *ua_chan;
+                       struct ust_app_session *ua_sess;
+                       struct ust_registry_session *registry;
+
+                       ua_sess = lookup_session_by_app(usess, app);
+                       if (!ua_sess) {
+                               /* Session not associated with this app. */
+                               continue;
+                       }
+                       ret = snprintf(pathname, sizeof(pathname),
+                                       DEFAULT_UST_TRACE_DIR "/%s",
+                                       ua_sess->path);
+                       if (ret < 0 || ret == sizeof(pathname)) {
+                               PERROR("Failed to format rotation path");
+                               goto error;
+                       }
+
+                       /* Get the right consumer socket for the application. */
+                       socket = consumer_find_socket_by_bitness(app->bits_per_long,
+                                       usess->consumer);
+                       if (!socket) {
+                               ret = -EINVAL;
+                               goto error;
+                       }
+
+                       registry = get_session_registry(ua_sess);
+                       if (!registry) {
+                               DBG("Application session is being torn down. Abort snapshot record.");
+                               ret = -1;
+                               goto error;
+                       }
+
+                       /*
+                        * Account the metadata channel first to make sure the
+                        * number of channels waiting for a rotation cannot
+                        * reach 0 before we complete the iteration over all
+                        * the channels.
+                        */
+                       ret = rotate_add_channel_pending(registry->metadata_key,
+                                       LTTNG_DOMAIN_UST, session);
+                       if (ret < 0) {
+                               ret = app->bits_per_long == 32 ?
+                                               -LTTNG_ERR_UST_CONSUMER32_FAIL :
+                                               -LTTNG_ERR_UST_CONSUMER64_FAIL;
+                               goto error;
+                       }
+
+                       /* Rotate the data channels. */
+                       cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter,
+                                       ua_chan, node.node) {
+                               ret = rotate_add_channel_pending(
+                                               ua_chan->key, LTTNG_DOMAIN_UST,
+                                               session);
+                               if (ret < 0) {
+                                       ret = app->bits_per_long == 32 ?
+                                                       -LTTNG_ERR_UST_CONSUMER32_FAIL :
+                                                       -LTTNG_ERR_UST_CONSUMER64_FAIL;
+                                       goto error;
+                               }
+                               ret = consumer_rotate_channel(socket, ua_chan->key,
+                                               ua_sess->euid, ua_sess->egid,
+                                               ua_sess->consumer, pathname,
+                                               /* is_metadata_channel */ false,
+                                               session->current_archive_id,
+                                               &session->rotate_pending_relay);
+                               if (ret < 0) {
+                                       goto error;
+                               }
+                       }
+
+                       /* Rotate the metadata channel. */
+                       (void) push_metadata(registry, usess->consumer);
+                       ret = consumer_rotate_channel(socket, registry->metadata_key,
+                                       ua_sess->euid, ua_sess->egid,
+                                       ua_sess->consumer, pathname,
+                                       /* is_metadata_channel */ true,
+                                       session->current_archive_id,
+                                       &session->rotate_pending_relay);
+                       if (ret < 0) {
+                               goto error;
+                       }
+                       *ust_active = true;
+               }
+               break;
+       }
+       default:
+               assert(0);
+               break;
+       }
+
+       ret = LTTNG_OK;
+
+error:
+       rcu_read_unlock();
+       return ret;
+}
This page took 0.03554 seconds and 4 git commands to generate.