Command metadata regenerate
[lttng-tools.git] / src / bin / lttng-sessiond / ust-app.c
index e3995bdf612d0e82a2fea38e0c4008fd4795b8f2..9a766e4ab68e628cbdec4d9f0432ec0b83dea547 100644 (file)
@@ -376,6 +376,8 @@ void delete_ust_app_channel_rcu(struct rcu_head *head)
  * Extract the lost packet or discarded events counter when the channel is
  * being deleted and store the value in the parent channel so we can
  * access it from lttng list and at stop/destroy.
+ *
+ * The session list lock must be held by the caller.
  */
 static
 void save_per_pid_lost_discarded_counters(struct ust_app_channel *ua_chan)
@@ -390,12 +392,22 @@ void save_per_pid_lost_discarded_counters(struct ust_app_channel *ua_chan)
 
        rcu_read_lock();
        session = session_find_by_id(ua_chan->session->tracing_id);
-       if (!session) {
-               ERR("Missing LTT session to get discarded events");
-               goto end;
-       }
-       if (!session->ust_session) {
-               ERR("Missing UST session to get discarded events");
+       if (!session || !session->ust_session) {
+               /*
+                * Not finding the session is not an error because there are
+                * multiple ways the channels can be torn down.
+                *
+                * 1) The session daemon can initiate the destruction of the
+                *    ust app session after receiving a destroy command or
+                *    during its shutdown/teardown.
+                * 2) The application, since we are in per-pid tracing, is
+                *    unregistering and tearing down its ust app session.
+                *
+                * Both paths are protected by the session list lock which
+                * ensures that the accounting of lost packets and discarded
+                * events is done exactly once. The session is then unpublished
+                * from the session list, resulting in this condition.
+                */
                goto end;
        }
 
@@ -426,6 +438,8 @@ end:
 /*
  * Delete ust app channel safely. RCU read lock must be held before calling
  * this function.
+ *
+ * The session list lock must be held by the caller.
  */
 static
 void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan,
@@ -537,7 +551,7 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
        char *metadata_str = NULL;
        size_t len, offset, new_metadata_len_sent;
        ssize_t ret_val;
-       uint64_t metadata_key;
+       uint64_t metadata_key, metadata_version;
 
        assert(registry);
        assert(socket);
@@ -567,6 +581,7 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
        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;
        if (len == 0) {
                DBG3("No metadata to push for metadata key %" PRIu64,
                                registry->metadata_key);
@@ -603,7 +618,7 @@ push_data:
         * different bidirectionnal communication sockets.
         */
        ret = consumer_push_metadata(socket, metadata_key,
-                       metadata_str, len, offset);
+                       metadata_str, len, offset, metadata_version);
        pthread_mutex_lock(&registry->lock);
        if (ret < 0) {
                /*
@@ -787,6 +802,8 @@ void delete_ust_app_session_rcu(struct rcu_head *head)
 /*
  * Delete ust app session safely. RCU read lock must be held before calling
  * this function.
+ *
+ * The session list lock must be held by the caller.
  */
 static
 void delete_ust_app_session(int sock, struct ust_app_session *ua_sess,
@@ -870,6 +887,11 @@ void delete_ust_app(struct ust_app *app)
        int ret, sock;
        struct ust_app_session *ua_sess, *tmp_ua_sess;
 
+       /*
+        * The session list lock must be held during this function to guarantee
+        * the existence of ua_sess.
+        */
+       session_lock_list();
        /* Delete ust app sessions info */
        sock = app->sock;
        app->sock = -1;
@@ -908,6 +930,7 @@ void delete_ust_app(struct ust_app *app)
 
        DBG2("UST app pid %d deleted", app->pid);
        free(app);
+       session_unlock_list();
 }
 
 /*
@@ -928,6 +951,8 @@ void delete_ust_app_rcu(struct rcu_head *head)
 /*
  * Delete the session from the application ht and delete the data structure by
  * freeing every object inside and releasing them.
+ *
+ * The session list lock must be held by the caller.
  */
 static void destroy_app_session(struct ust_app *app,
                struct ust_app_session *ua_sess)
@@ -5955,7 +5980,7 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
                }
 
                /* Get channel */
-               lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter);
+               lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &uiter);
                ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
                /* If the session is found for the app, the channel must be there */
                assert(ua_chan_node);
@@ -5971,7 +5996,6 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
                                        ua_chan->key, consumer, discarded);
                        goto end;
                }
-               goto end;
        }
 
 end:
This page took 0.025762 seconds and 4 git commands to generate.