Fix: sessiond: ODR violation results in memory corruption
[lttng-tools.git] / src / bin / lttng-sessiond / ust-metadata.cpp
index f5c5e7a2136c9cb2a533e4f90a6f1cfa08aef811..3a2eb5ca2446b5042884d5917c468df281cb3bf5 100644 (file)
 #include <inttypes.h>
 #include <common/common.hpp>
 #include <common/time.hpp>
+#include <vector>
 
 #include "ust-registry.hpp"
 #include "ust-clock.hpp"
 #include "ust-app.hpp"
 
-#ifndef max_t
-#define max_t(type, a, b)      ((type) ((a) > (b) ? (a) : (b)))
-#endif
-
 #define NR_CLOCK_OFFSET_SAMPLES                10
 
+namespace {
 struct offset_sample {
-       int64_t offset;                 /* correlation offset */
-       uint64_t measure_delta;         /* lower is better */
+       /* correlation offset */
+       int64_t offset;
+       /* lower is better */
+       uint64_t measure_delta;
 };
+} /* namespace */
 
 static
 int _lttng_field_statedump(struct ust_registry_session *session,
@@ -69,7 +70,7 @@ ssize_t metadata_reserve(struct ust_registry_session *session, size_t len)
                char *newptr;
 
                new_alloc_len =
-                       max_t(size_t, 1U << get_count_order(new_alloc_len), old_alloc_len << 1);
+                       std::max<size_t>(1U << get_count_order(new_alloc_len), old_alloc_len << 1);
                newptr = (char *) realloc(session->metadata, new_alloc_len);
                if (!newptr)
                        return -ENOMEM;
@@ -845,6 +846,16 @@ int ust_metadata_event_statedump(struct ust_registry_session *session,
        if (chan->chan_id == -1U)
                return 0;
 
+       /*
+        * We don't want to output an event's metadata before its parent
+        * stream's metadata.  If the stream's metadata hasn't been output yet,
+        * skip this event.  Its metadata will be output when we output the
+        * stream's metadata.
+        */
+       if (!chan->metadata_dumped || event->metadata_dumped) {
+               return 0;
+       }
+
        ret = lttng_metadata_printf(session,
                "event {\n"
                "       name = \"%s\";\n"
@@ -899,11 +910,15 @@ end:
 
 /*
  * Should be called with session registry mutex held.
+ *
+ * RCU read lock must be held by the caller.
  */
 int ust_metadata_channel_statedump(struct ust_registry_session *session,
                struct ust_registry_channel *chan)
 {
-       int ret = 0;
+       int ret;
+
+       ASSERT_RCU_READ_LOCKED();
 
        /* Don't dump metadata events */
        if (chan->chan_id == -1U)
@@ -922,37 +937,65 @@ int ust_metadata_channel_statedump(struct ust_registry_session *session,
                        "struct event_header_compact" :
                        "struct event_header_large");
        if (ret) {
-               goto end;
+               return ret;
        }
 
        if (chan->ctx_fields) {
                ret = lttng_metadata_printf(session,
                        "       event.context := struct {\n");
                if (ret) {
-                       goto end;
+                       return ret;
                }
        }
        ret = _lttng_context_metadata_statedump(session,
                chan->nr_ctx_fields,
                chan->ctx_fields);
        if (ret) {
-               goto end;
+               return ret;
        }
        if (chan->ctx_fields) {
                ret = lttng_metadata_printf(session,
                        "       };\n");
                if (ret) {
-                       goto end;
+                       return ret;
                }
        }
 
        ret = lttng_metadata_printf(session,
                "};\n\n");
+       if (ret) {
+               return ret;
+       }
+
        /* Flag success of metadata dump. */
        chan->metadata_dumped = 1;
 
-end:
-       return ret;
+       /*
+        * Output the metadata of any existing event.
+        *
+        * Sort the events by id.  This is not necessary, but it's nice to have
+        * a more predictable order in the metadata file.
+        */
+       std::vector<ust_registry_event *> events;
+       {
+               cds_lfht_iter event_iter;
+               ust_registry_event *event;
+               cds_lfht_for_each_entry(chan->events->ht, &event_iter, event,
+                               node.node) {
+                       events.push_back(event);
+               }
+       }
+
+       std::sort(events.begin(), events.end(),
+               [] (ust_registry_event *a, ust_registry_event *b) {
+                       return a->id < b->id;
+               });
+
+       for (ust_registry_event *event : events) {
+               ust_metadata_event_statedump(session, chan, event);
+       }
+
+       return 0;
 }
 
 static
This page took 0.024306 seconds and 4 git commands to generate.