Fix: UST should not generate packet at destroy after stop
[lttng-tools.git] / src / bin / lttng-sessiond / ust-app.c
index 9b634facc1422630827e5e92268839ef37b20146..f30df2097fd36aea2b03d2f30f96d791226dc1a9 100644 (file)
@@ -551,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);
@@ -581,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);
@@ -617,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) {
                /*
@@ -2820,9 +2821,6 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *reg_chan,
                        (void) release_ust_app_stream(-1, &stream, app);
                        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                                ret = -ENOTCONN; /* Caused by app exiting. */
-                               goto error_stream_unlock;
-                       } else if (ret < 0) {
-                               goto error_stream_unlock;
                        }
                        goto error_stream_unlock;
                }
@@ -4649,6 +4647,155 @@ int ust_app_flush_session(struct ltt_ust_session *usess)
        return ret;
 }
 
+static
+int ust_app_clear_quiescent_app_session(struct ust_app *app,
+               struct ust_app_session *ua_sess)
+{
+       int ret = 0;
+       struct lttng_ht_iter iter;
+       struct ust_app_channel *ua_chan;
+       struct consumer_socket *socket;
+
+       DBG("Clearing stream quiescent state for ust app pid %d", app->pid);
+
+       rcu_read_lock();
+
+       if (!app->compatible) {
+               goto end_not_compatible;
+       }
+
+       pthread_mutex_lock(&ua_sess->lock);
+
+       if (ua_sess->deleted) {
+               goto end_unlock;
+       }
+
+       health_code_update();
+
+       socket = consumer_find_socket_by_bitness(app->bits_per_long,
+                       ua_sess->consumer);
+       if (!socket) {
+               ERR("Failed to find consumer (%" PRIu32 ") socket",
+                               app->bits_per_long);
+               ret = -1;
+               goto end_unlock;
+       }
+
+       /* Clear quiescent state. */
+       switch (ua_sess->buffer_type) {
+       case LTTNG_BUFFER_PER_PID:
+               cds_lfht_for_each_entry(ua_sess->channels->ht, &iter.iter,
+                               ua_chan, node.node) {
+                       health_code_update();
+                       ret = consumer_clear_quiescent_channel(socket,
+                                       ua_chan->key);
+                       if (ret) {
+                               ERR("Error clearing quiescent state for consumer channel");
+                               ret = -1;
+                               continue;
+                       }
+               }
+               break;
+       case LTTNG_BUFFER_PER_UID:
+       default:
+               assert(0);
+               ret = -1;
+               break;
+       }
+
+       health_code_update();
+
+end_unlock:
+       pthread_mutex_unlock(&ua_sess->lock);
+
+end_not_compatible:
+       rcu_read_unlock();
+       health_code_update();
+       return ret;
+}
+
+/*
+ * Clear quiescent state in each stream for all applications for a
+ * specific UST session.
+ * Called with UST session lock held.
+ */
+static
+int ust_app_clear_quiescent_session(struct ltt_ust_session *usess)
+
+{
+       int ret = 0;
+
+       DBG("Clearing stream quiescent state for all ust apps");
+
+       rcu_read_lock();
+
+       switch (usess->buffer_type) {
+       case LTTNG_BUFFER_PER_UID:
+       {
+               struct lttng_ht_iter iter;
+               struct buffer_reg_uid *reg;
+
+               /*
+                * Clear quiescent for all per UID buffers associated to
+                * that session.
+                */
+               cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
+                       struct consumer_socket *socket;
+                       struct buffer_reg_channel *reg_chan;
+
+                       /* Get associated consumer socket.*/
+                       socket = consumer_find_socket_by_bitness(
+                                       reg->bits_per_long, usess->consumer);
+                       if (!socket) {
+                               /*
+                                * Ignore request if no consumer is found for
+                                * the session.
+                                */
+                               continue;
+                       }
+
+                       cds_lfht_for_each_entry(reg->registry->channels->ht,
+                                       &iter.iter, reg_chan, node.node) {
+                               /*
+                                * The following call will print error values so
+                                * the return code is of little importance
+                                * because whatever happens, we have to try them
+                                * all.
+                                */
+                               (void) consumer_clear_quiescent_channel(socket,
+                                               reg_chan->consumer_key);
+                       }
+               }
+               break;
+       }
+       case LTTNG_BUFFER_PER_PID:
+       {
+               struct ust_app_session *ua_sess;
+               struct lttng_ht_iter iter;
+               struct ust_app *app;
+
+               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app,
+                               pid_n.node) {
+                       ua_sess = lookup_session_by_app(usess, app);
+                       if (ua_sess == NULL) {
+                               continue;
+                       }
+                       (void) ust_app_clear_quiescent_app_session(app,
+                                       ua_sess);
+               }
+               break;
+       }
+       default:
+               ret = -1;
+               assert(0);
+               break;
+       }
+
+       rcu_read_unlock();
+       health_code_update();
+       return ret;
+}
+
 /*
  * Destroy a specific UST session in apps.
  */
@@ -4707,6 +4854,14 @@ int ust_app_start_trace_all(struct ltt_ust_session *usess)
 
        rcu_read_lock();
 
+       /*
+        * In a start-stop-start use-case, we need to clear the quiescent state
+        * of each channel set by the prior stop command, thus ensuring that a
+        * following stop or destroy is sure to grab a timestamp_end near those
+        * operations, even if the packet is empty.
+        */
+       (void) ust_app_clear_quiescent_session(usess);
+
        cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                ret = ust_app_start_trace(usess, app);
                if (ret < 0) {
@@ -5725,7 +5880,6 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess,
                uint64_t nb_packets_per_stream)
 {
        int ret = 0;
-       unsigned int snapshot_done = 0;
        struct lttng_ht_iter iter;
        struct ust_app *app;
        char pathname[PATH_MAX];
@@ -5777,7 +5931,6 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess,
                        if (ret < 0) {
                                goto error;
                        }
-                       snapshot_done = 1;
                }
                break;
        }
@@ -5830,7 +5983,6 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess,
                        if (ret < 0) {
                                goto error;
                        }
-                       snapshot_done = 1;
                }
                break;
        }
@@ -5839,15 +5991,6 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess,
                break;
        }
 
-       if (!snapshot_done) {
-               /*
-                * If no snapshot was made and we are not in the error path, this means
-                * that there are no buffers thus no (prior) application to snapshot
-                * data from so we have simply NO data.
-                */
-               ret = -ENODATA;
-       }
-
 error:
        rcu_read_unlock();
        return ret;
@@ -5944,9 +6087,11 @@ int ust_app_uid_get_channel_runtime_stats(uint64_t ust_session_id,
        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:
@@ -5989,10 +6134,12 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
                if (overwrite) {
                        ret = consumer_get_lost_packets(usess->id, ua_chan->key,
                                        consumer, lost);
+                       *discarded = 0;
                        goto end;
                } else {
                        ret = consumer_get_discarded_events(usess->id,
                                        ua_chan->key, consumer, discarded);
+                       *lost = 0;
                        goto end;
                }
        }
This page took 0.026825 seconds and 4 git commands to generate.