Fix: filter attach vs event enable race
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 12 Nov 2014 23:18:32 +0000 (18:18 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sun, 16 Nov 2014 14:08:29 +0000 (09:08 -0500)
In order to correctly handle the use-case where events are enabled
_after_ trace is started, and _after_ applications are already being
traced, the event should be created in a "disabled" state, so that it
does not trace events until its filter is attached.

This fix needs to be done both in lttng-tools and lttng-ust. In order to
keep ABI compatibility between tools and ust within a stable release
cycle, we introduce a new "disabled" within struct lttng_ust_event
padding (previously zeroed). Newer LTTng-UST checks this flag, and
fallback on the old racy behavior (enabling the event on creation) if it
is unset.

Therefore, old session daemon works with newer lttng-ust of the same
stable release, and vice-versa. However, building lttng-tools requires
an upgraded lttng-ust, which contains the communication protocol with
the new "disabled" field.

This patch should be backported to stable-2.4, stable-2.5, stable-2.6
branches.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-sessiond/trace-ust.c
src/bin/lttng-sessiond/ust-app.c

index 96225a21b4846e974ffb1f900c054202759e3b5a..ddf5dc4abb057d8611387585754cfb34ea93302d 100644 (file)
@@ -393,6 +393,11 @@ struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev,
                ERR("Unknown ust loglevel type (%d)", ev->loglevel_type);
                goto error_free_event;
        }
+       /*
+        * Fix for enabler race. Enable is now done explicitly by
+        * sessiond after setting filter.
+        */
+       lue->attr.disabled = 1;
 
        /* Same layout. */
        lue->filter_expression = filter_expression;
index 4a7fadaf5231d4f3c84d33d7956f68f11dd998d5..bffceefd92cf3c8a36ce6e7892d8831bebd5979a 100644 (file)
@@ -1446,7 +1446,32 @@ int create_ust_event(struct ust_app *app, struct ust_app_session *ua_sess,
        }
 
        /* If event not enabled, disable it on the tracer */
-       if (ua_event->enabled == 0) {
+       if (ua_event->enabled) {
+               /*
+                * We now need to explicitly enable the event, since it
+                * is now disabled at creation.
+                */
+               ret = enable_ust_event(app, ua_sess, ua_event);
+               if (ret < 0) {
+                       /*
+                        * If we hit an EPERM, something is wrong with our enable call. If
+                        * we get an EEXIST, there is a problem on the tracer side since we
+                        * just created it.
+                        */
+                       switch (ret) {
+                       case -LTTNG_UST_ERR_PERM:
+                               /* Code flow problem */
+                               assert(0);
+                       case -LTTNG_UST_ERR_EXIST:
+                               /* It's OK for our use case. */
+                               ret = 0;
+                               break;
+                       default:
+                               break;
+                       }
+                       goto error;
+               }
+       } else {
                ret = disable_ust_event(app, ua_sess, ua_event);
                if (ret < 0) {
                        /*
This page took 0.029313 seconds and 4 git commands to generate.