Fix: filter attach vs event enable race
[lttng-ust.git] / liblttng-ust / lttng-events.c
index 6e16cf2548f04087ec3d1b6805736d3da1f179b5..8bdb743d93da21c0f8f1af62dcab2018956fa876 100644 (file)
 #include "jhash.h"
 
 /*
- * The sessions mutex is the centralized mutex across UST tracing
- * control and probe registration. All operations within this file are
- * called by the communication thread, under ust_lock protection.
+ * All operations within this file are called by the communication
+ * thread, under ust_lock protection.
  */
-static pthread_mutex_t sessions_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-void ust_lock(void)
-{
-       pthread_mutex_lock(&sessions_mutex);
-}
-
-void ust_unlock(void)
-{
-       pthread_mutex_unlock(&sessions_mutex);
-}
 
 static CDS_LIST_HEAD(sessions);
 
@@ -112,24 +100,27 @@ int lttng_loglevel_match(int loglevel,
                enum lttng_ust_loglevel_type req_type,
                int req_loglevel)
 {
-       if (req_type == LTTNG_UST_LOGLEVEL_ALL)
-               return 1;
        if (!has_loglevel)
                loglevel = TRACE_DEFAULT;
        switch (req_type) {
        case LTTNG_UST_LOGLEVEL_RANGE:
-               if (loglevel <= req_loglevel || req_loglevel == -1)
+               if (loglevel <= req_loglevel
+                               || (req_loglevel == -1 && loglevel <= TRACE_DEBUG))
                        return 1;
                else
                        return 0;
        case LTTNG_UST_LOGLEVEL_SINGLE:
-               if (loglevel == req_loglevel || req_loglevel == -1)
+               if (loglevel == req_loglevel
+                               || (req_loglevel == -1 && loglevel <= TRACE_DEBUG))
                        return 1;
                else
                        return 0;
        case LTTNG_UST_LOGLEVEL_ALL:
        default:
-               return 1;
+               if (loglevel <= TRACE_DEBUG)
+                       return 1;
+               else
+                       return 0;
        }
 }
 
@@ -257,8 +248,6 @@ int lttng_session_enable(struct lttng_session *session)
 
        /* Set transient enabler state to "enabled" */
        session->tstate = 1;
-       /* We need to sync enablers with session before activation. */
-       lttng_session_sync_enablers(session);
 
        /*
         * Snapshot the number of events per channel to know the type of header
@@ -296,6 +285,9 @@ int lttng_session_enable(struct lttng_session *session)
                }
        }
 
+       /* We need to sync enablers with session before activation. */
+       lttng_session_sync_enablers(session);
+
        /* Set atomically the state to "active" */
        CMM_ACCESS_ONCE(session->active) = 1;
        CMM_ACCESS_ONCE(session->been_active) = 1;
@@ -686,7 +678,7 @@ int lttng_fix_pending_events(void)
  * Only dump state for the sessions owned by the caller thread, because
  * we don't keep ust_lock across the entire iteration.
  */
-int lttng_handle_pending_statedump(void *owner)
+void lttng_handle_pending_statedump(void *owner)
 {
        struct lttng_session *session;
 
@@ -694,7 +686,9 @@ int lttng_handle_pending_statedump(void *owner)
        lttng_ust_baddr_statedump(owner);
 
        /* Clear pending state dump */
-       ust_lock();
+       if (ust_lock()) {
+               goto end;
+       }
        cds_list_for_each_entry(session, &sessions, node) {
                if (session->owner != owner)
                        continue;
@@ -702,8 +696,9 @@ int lttng_handle_pending_statedump(void *owner)
                        continue;
                session->statedump_pending = 0;
        }
+end:
        ust_unlock();
-       return 0;
+       return;
 }
 
 /*
@@ -751,7 +746,16 @@ struct lttng_enabler *lttng_enabler_create(enum lttng_enabler_type type,
                sizeof(enabler->event_param));
        enabler->chan = chan;
        /* ctx left NULL */
-       enabler->enabled = 1;
+       /*
+        * The "disable" event create comm field has been added to fix a
+        * race between event creation (of a started trace) and enabling
+        * filtering. New session daemon always set the "disable" field
+        * to 1, and are aware that they need to explicitly enable the
+        * event. Older session daemon (within same ABI) leave it at 0,
+        * and therefore we need to enable it here, keeping the original
+        * racy behavior.
+        */
+       enabler->enabled = !event_param->disabled;
        cds_list_add(&enabler->node, &enabler->chan->session->enablers_head);
        lttng_session_lazy_sync_enablers(enabler->chan->session);
        return enabler;
@@ -803,6 +807,17 @@ int lttng_attach_context(struct lttng_ust_context *context_param,
        switch (context_param->ctx) {
        case LTTNG_UST_CONTEXT_PTHREAD_ID:
                return lttng_add_pthread_id_to_ctx(ctx);
+       case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
+       {
+               struct lttng_ust_perf_counter_ctx *perf_ctx_param;
+
+               perf_ctx_param = &context_param->u.perf_counter;
+               return lttng_add_perf_counter_to_ctx(
+                       perf_ctx_param->type,
+                       perf_ctx_param->config,
+                       perf_ctx_param->name,
+                       ctx);
+       }
        case LTTNG_UST_CONTEXT_VTID:
                return lttng_add_vtid_to_ctx(ctx);
        case LTTNG_UST_CONTEXT_VPID:
This page took 0.024215 seconds and 4 git commands to generate.