Fix: handle backward probe compatibility for application contexts
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 10 Mar 2016 01:05:53 +0000 (20:05 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 10 Mar 2016 01:09:00 +0000 (20:09 -0500)
Fix segmentation fault of applications built against lttng-ust 2.7,
linked against lttng-ust 2.8-pre when tracing is active. We need to
consider backward ABI compability here, which can be done by using
a dummy context in place of an application context when recording an
event. Basically, application contexts won't be saved into events
generated by a lttng-ust 2.7 probe provider: those will appear as empty
contexts.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
liblttng-ust/lttng-context-provider.c
liblttng-ust/lttng-ring-buffer-client.h
liblttng-ust/lttng-tracer-core.h

index e7462cdabec945522c697576c632511f97043567..b5ae3075c075d1c70a797e5014f98ccb92a20d2d 100644 (file)
@@ -92,8 +92,7 @@ end:
        return ret;
 }
 
-static
-size_t dummy_get_size(struct lttng_ctx_field *field, size_t offset)
+size_t lttng_ust_dummy_get_size(struct lttng_ctx_field *field, size_t offset)
 {
        size_t size = 0;
 
@@ -102,8 +101,7 @@ size_t dummy_get_size(struct lttng_ctx_field *field, size_t offset)
        return size;
 }
 
-static
-void dummy_record(struct lttng_ctx_field *field,
+void lttng_ust_dummy_record(struct lttng_ctx_field *field,
                 struct lttng_ust_lib_ring_buffer_ctx *ctx,
                 struct lttng_channel *chan)
 {
@@ -113,8 +111,7 @@ void dummy_record(struct lttng_ctx_field *field,
        chan->ops->event_write(ctx, &sel_char, sizeof(sel_char));
 }
 
-static
-void dummy_get_value(struct lttng_ctx_field *field,
+void lttng_ust_dummy_get_value(struct lttng_ctx_field *field,
                struct lttng_ctx_value *value)
 {
        value->sel = LTTNG_UST_DYNAMIC_TYPE_NONE;
@@ -125,7 +122,8 @@ void lttng_ust_context_provider_unregister(struct lttng_ust_context_provider *pr
        if (ust_lock())
                goto end;
        lttng_ust_context_set_session_provider(provider->name,
-               dummy_get_size, dummy_record, dummy_get_value);
+               lttng_ust_dummy_get_size, lttng_ust_dummy_record,
+               lttng_ust_dummy_get_value);
        cds_hlist_del(&provider->node);
 end:
        ust_unlock();
@@ -168,9 +166,9 @@ int lttng_ust_add_app_context_to_ctx_rcu(const char *name,
                new_field.record = provider->record;
                new_field.get_value = provider->get_value;
        } else {
-               new_field.get_size = dummy_get_size;
-               new_field.record = dummy_record;
-               new_field.get_value = dummy_get_value;
+               new_field.get_size = lttng_ust_dummy_get_size;
+               new_field.record = lttng_ust_dummy_record;
+               new_field.get_value = lttng_ust_dummy_get_value;
        }
        ret = lttng_context_add_rcu(ctx, &new_field);
        if (ret) {
index 1ebb14e48ff05e218994dbc8710eb566b22f9fcd..e5640b2ea0e4e7096e8729e975f75141b0892692 100644 (file)
 #define LTTNG_COMPACT_EVENT_BITS       5
 #define LTTNG_COMPACT_TSC_BITS         27
 
+enum app_ctx_mode {
+       APP_CTX_DISABLED,
+       APP_CTX_ENABLED,
+};
+
 /*
  * Keep the natural field alignment for _each field_ within this structure if
  * you ever add/remove a field from this header. Packed attribute is not used
@@ -71,7 +76,8 @@ static inline uint64_t lib_ring_buffer_clock_read(struct channel *chan)
 }
 
 static inline
-size_t ctx_get_size(size_t offset, struct lttng_ctx *ctx)
+size_t ctx_get_size(size_t offset, struct lttng_ctx *ctx,
+               enum app_ctx_mode mode)
 {
        int i;
        size_t orig_offset = offset;
@@ -79,23 +85,62 @@ size_t ctx_get_size(size_t offset, struct lttng_ctx *ctx)
        if (caa_likely(!ctx))
                return 0;
        offset += lib_ring_buffer_align(offset, ctx->largest_align);
-       for (i = 0; i < ctx->nr_fields; i++)
-               offset += ctx->fields[i].get_size(&ctx->fields[i], offset);
+       for (i = 0; i < ctx->nr_fields; i++) {
+               if (mode == APP_CTX_ENABLED) {
+                       offset += ctx->fields[i].get_size(&ctx->fields[i], offset);
+               } else {
+                       if (lttng_context_is_app(ctx->fields[i].event_field.name)) {
+                               /*
+                                * Before UST 2.8, we cannot use the
+                                * application context, because we
+                                * cannot trust that the handler used
+                                * for get_size is the same used for
+                                * ctx_record, which would result in
+                                * corrupted traces when tracing
+                                * concurrently with application context
+                                * register/unregister.
+                                */
+                               offset += lttng_ust_dummy_get_size(&ctx->fields[i], offset);
+                       } else {
+                               offset += ctx->fields[i].get_size(&ctx->fields[i], offset);
+                       }
+               }
+       }
        return offset - orig_offset;
 }
 
 static inline
 void ctx_record(struct lttng_ust_lib_ring_buffer_ctx *bufctx,
                struct lttng_channel *chan,
-               struct lttng_ctx *ctx)
+               struct lttng_ctx *ctx,
+               enum app_ctx_mode mode)
 {
        int i;
 
        if (caa_likely(!ctx))
                return;
        lib_ring_buffer_align_ctx(bufctx, ctx->largest_align);
-       for (i = 0; i < ctx->nr_fields; i++)
-               ctx->fields[i].record(&ctx->fields[i], bufctx, chan);
+       for (i = 0; i < ctx->nr_fields; i++) {
+               if (mode == APP_CTX_ENABLED) {
+                       ctx->fields[i].record(&ctx->fields[i], bufctx, chan);
+               } else {
+                       if (lttng_context_is_app(ctx->fields[i].event_field.name)) {
+                               /*
+                                * Before UST 2.8, we cannot use the
+                                * application context, because we
+                                * cannot trust that the handler used
+                                * for get_size is the same used for
+                                * ctx_record, which would result in
+                                * corrupted traces when tracing
+                                * concurrently with application context
+                                * register/unregister.
+                                */
+                               lttng_ust_dummy_record(&ctx->fields[i], bufctx, chan);
+                       } else {
+                               ctx->fields[i].record(&ctx->fields[i], bufctx, chan);
+                       }
+               }
+       }
 }
 
 /*
@@ -118,6 +163,7 @@ size_t record_header_size(const struct lttng_ust_lib_ring_buffer_config *config,
                                 struct lttng_ust_lib_ring_buffer_ctx *ctx)
 {
        struct lttng_channel *lttng_chan = channel_get_private(chan);
+       struct lttng_event *event = ctx->priv;
        struct lttng_stack_ctx *lttng_ctx = ctx->priv2;
        size_t orig_offset = offset;
        size_t padding;
@@ -157,9 +203,15 @@ size_t record_header_size(const struct lttng_ust_lib_ring_buffer_config *config,
                padding = 0;
                WARN_ON_ONCE(1);
        }
-       offset += ctx_get_size(offset, lttng_ctx->chan_ctx);
-       offset += ctx_get_size(offset, lttng_ctx->event_ctx);
-
+       if (lttng_ctx) {
+               /* 2.8+ probe ABI. */
+               offset += ctx_get_size(offset, lttng_ctx->chan_ctx, APP_CTX_ENABLED);
+               offset += ctx_get_size(offset, lttng_ctx->event_ctx, APP_CTX_ENABLED);
+       } else {
+               /* Pre 2.8 probe ABI. */
+               offset += ctx_get_size(offset, lttng_chan->ctx, APP_CTX_DISABLED);
+               offset += ctx_get_size(offset, event->ctx, APP_CTX_DISABLED);
+       }
        *pre_header_padding = padding;
        return offset - orig_offset;
 }
@@ -187,6 +239,7 @@ void lttng_write_event_header(const struct lttng_ust_lib_ring_buffer_config *con
                            uint32_t event_id)
 {
        struct lttng_channel *lttng_chan = channel_get_private(ctx->chan);
+       struct lttng_event *event = ctx->priv;
        struct lttng_stack_ctx *lttng_ctx = ctx->priv2;
 
        if (caa_unlikely(ctx->rflags))
@@ -222,8 +275,15 @@ void lttng_write_event_header(const struct lttng_ust_lib_ring_buffer_config *con
                WARN_ON_ONCE(1);
        }
 
-       ctx_record(ctx, lttng_chan, lttng_ctx->chan_ctx);
-       ctx_record(ctx, lttng_chan, lttng_ctx->event_ctx);
+       if (lttng_ctx) {
+               /* 2.8+ probe ABI. */
+               ctx_record(ctx, lttng_chan, lttng_ctx->chan_ctx, APP_CTX_ENABLED);
+               ctx_record(ctx, lttng_chan, lttng_ctx->event_ctx, APP_CTX_ENABLED);
+       } else {
+               /* Pre 2.8 probe ABI. */
+               ctx_record(ctx, lttng_chan, lttng_chan->ctx, APP_CTX_DISABLED);
+               ctx_record(ctx, lttng_chan, event->ctx, APP_CTX_DISABLED);
+       }
        lib_ring_buffer_align_ctx(ctx, ctx->largest_align);
 
        return;
@@ -238,6 +298,7 @@ void lttng_write_event_header_slow(const struct lttng_ust_lib_ring_buffer_config
                                 uint32_t event_id)
 {
        struct lttng_channel *lttng_chan = channel_get_private(ctx->chan);
+       struct lttng_event *event = ctx->priv;
        struct lttng_stack_ctx *lttng_ctx = ctx->priv2;
 
        switch (lttng_chan->header_type) {
@@ -295,8 +356,15 @@ void lttng_write_event_header_slow(const struct lttng_ust_lib_ring_buffer_config
        default:
                WARN_ON_ONCE(1);
        }
-       ctx_record(ctx, lttng_chan, lttng_ctx->chan_ctx);
-       ctx_record(ctx, lttng_chan, lttng_ctx->event_ctx);
+       if (lttng_ctx) {
+               /* 2.8+ probe ABI. */
+               ctx_record(ctx, lttng_chan, lttng_ctx->chan_ctx, APP_CTX_ENABLED);
+               ctx_record(ctx, lttng_chan, lttng_ctx->event_ctx, APP_CTX_ENABLED);
+       } else {
+               /* Pre 2.8 probe ABI. */
+               ctx_record(ctx, lttng_chan, lttng_chan->ctx, APP_CTX_DISABLED);
+               ctx_record(ctx, lttng_chan, event->ctx, APP_CTX_DISABLED);
+       }
        lib_ring_buffer_align_ctx(ctx, ctx->largest_align);
 }
 
index 7d9beaaf92ca70ae0e48eb317f718ff759e93aee..44aca749c6c04553702e2ecd54313657bd27b777 100644 (file)
@@ -33,6 +33,9 @@
 struct lttng_session;
 struct lttng_channel;
 struct lttng_event;
+struct lttng_ctx_field;
+struct lttng_ust_lib_ring_buffer_ctx;
+struct lttng_ctx_value;
 
 int ust_lock(void) __attribute__ ((warn_unused_result));
 void ust_lock_nocheck(void);
@@ -52,4 +55,12 @@ void lttng_ust_malloc_wrapper_init(void);
 
 ssize_t lttng_ust_read(int fd, void *buf, size_t len);
 
+size_t lttng_ust_dummy_get_size(struct lttng_ctx_field *field, size_t offset);
+void lttng_ust_dummy_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct lttng_channel *chan);
+void lttng_ust_dummy_get_value(struct lttng_ctx_field *field,
+               struct lttng_ctx_value *value);
+int lttng_context_is_app(const char *name);
+
 #endif /* _LTTNG_TRACER_CORE_H */
This page took 0.028608 seconds and 4 git commands to generate.