Support unloading of probe providers
authorFrancis Deslauriers <francis.deslauriers@efficios.com>
Fri, 9 Feb 2018 20:15:25 +0000 (15:15 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 9 Feb 2018 20:41:34 +0000 (15:41 -0500)
With this commit, it's now possible to dlclose() a library containing an
actively used probe provider.

The destructor of such library will now iterate over all the sessions
and over all probe definitions to unregister them from the respective
callsites in the process.

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
liblttng-ust/lttng-events.c
liblttng-ust/lttng-probes.c
liblttng-ust/tracepoint.c

index e130ec626d35f3f6d140737d51151245acbc51a6..255c4b953f9055141e72fae3449c37da5e56cb6b 100644 (file)
@@ -798,7 +798,7 @@ void lttng_probe_provider_unregister_events(struct lttng_probe_desc *provider_de
        struct lttng_session *session;
        struct cds_hlist_head *head;
        struct lttng_event *event;
-       int i;
+       unsigned int i, j;
 
        /* Get handle on list of sessions. */
        sessionsp = _lttng_get_sessions();
index a09497f87ba444adc58a1765d0757a04fda7a809..862b19e7c47e3c7c5b5e262e5b1bc02edf3c090f 100644 (file)
@@ -226,7 +226,10 @@ void lttng_probe_unregister(struct lttng_probe_desc *desc)
                cds_list_del(&desc->head);
        else
                cds_list_del(&desc->lazy_init_head);
-       DBG("just unregistered probe %s", desc->provider);
+
+       lttng_probe_provider_unregister_events(desc);
+       DBG("just unregistered probes of provider %s", desc->provider);
+
        ust_unlock();
 }
 
index 14b8231f879fca9d3aa8e3bde5a6a661cbb6b4c2..2c25d46250b603c6ed3e5c987f24aae905ef482a 100644 (file)
@@ -107,8 +107,8 @@ struct tracepoint_entry {
        struct lttng_ust_tracepoint_probe *probes;
        int refcount;   /* Number of times armed. 0 if disarmed. */
        int callsite_refcount;  /* how many libs use this tracepoint */
-       const char *signature;
-       char name[0];
+       char *signature;
+       char *name;
 };
 
 struct tp_probes {
@@ -132,6 +132,7 @@ struct callsite_entry {
        struct cds_hlist_node hlist;    /* hash table node */
        struct cds_list_head node;      /* lib list of callsites node */
        struct lttng_ust_tracepoint *tp;
+       bool tp_entry_callsite_ref; /* Has a tp_entry took a ref on this callsite */
 };
 
 /* coverity[+alloc] */
@@ -284,6 +285,8 @@ static struct tracepoint_entry *add_tracepoint(const char *name,
        struct cds_hlist_node *node;
        struct tracepoint_entry *e;
        size_t name_len = strlen(name);
+       size_t sig_len = strlen(signature);
+       size_t sig_off, name_off;
        uint32_t hash;
 
        if (name_len > LTTNG_UST_SYM_NAME_LEN - 1) {
@@ -298,19 +301,29 @@ static struct tracepoint_entry *add_tracepoint(const char *name,
                        return ERR_PTR(-EEXIST);        /* Already there */
                }
        }
+
        /*
-        * Using zmalloc here to allocate a variable length element. Could
-        * cause some memory fragmentation if overused.
+        * Using zmalloc here to allocate a variable length elements: name and
+        * signature. Could cause some memory fragmentation if overused.
         */
-       e = zmalloc(sizeof(struct tracepoint_entry) + name_len + 1);
+       name_off = sizeof(struct tracepoint_entry);
+       sig_off = name_off + name_len + 1;
+
+       e = zmalloc(sizeof(struct tracepoint_entry) + name_len + 1 + sig_len + 1);
        if (!e)
                return ERR_PTR(-ENOMEM);
-       memcpy(&e->name[0], name, name_len + 1);
+       e->name = (char *) e + name_off;
+       memcpy(e->name, name, name_len + 1);
        e->name[name_len] = '\0';
+
+       e->signature = (char *) e + sig_off;
+       memcpy(e->signature, signature, sig_len + 1);
+       e->signature[sig_len] = '\0';
+
        e->probes = NULL;
        e->refcount = 0;
        e->callsite_refcount = 0;
-       e->signature = signature;
+
        cds_hlist_add_head(&e->hlist, head);
        return e;
 }
@@ -405,6 +418,7 @@ static void add_callsite(struct tracepoint_lib * lib, struct lttng_ust_tracepoin
        if (!tp_entry)
                return;
        tp_entry->callsite_refcount++;
+       e->tp_entry_callsite_ref = true;
 }
 
 /*
@@ -417,7 +431,8 @@ static void remove_callsite(struct callsite_entry *e)
 
        tp_entry = get_tracepoint(e->tp->name);
        if (tp_entry) {
-               tp_entry->callsite_refcount--;
+               if (e->tp_entry_callsite_ref)
+                       tp_entry->callsite_refcount--;
                if (tp_entry->callsite_refcount == 0)
                        disable_tracepoint(e->tp);
        }
@@ -453,10 +468,15 @@ static void tracepoint_sync_callsites(const char *name)
                if (strncmp(name, tp->name, LTTNG_UST_SYM_NAME_LEN - 1))
                        continue;
                if (tp_entry) {
+                       if (!e->tp_entry_callsite_ref) {
+                               tp_entry->callsite_refcount++;
+                               e->tp_entry_callsite_ref = true;
+                       }
                        set_tracepoint(&tp_entry, tp,
                                        !!tp_entry->refcount);
                } else {
                        disable_tracepoint(tp);
+                       e->tp_entry_callsite_ref = false;
                }
        }
 }
@@ -545,7 +565,12 @@ tracepoint_add_probe(const char *name, void (*probe)(void), void *data,
        struct lttng_ust_tracepoint_probe *old;
 
        entry = get_tracepoint(name);
-       if (!entry) {
+       if (entry) {
+               if (strcmp(entry->signature, signature) != 0) {
+                       ERR("Tracepoint and probe signature do not match.");
+                       return ERR_PTR(-EINVAL);
+               }
+       } else {
                entry = add_tracepoint(name, signature);
                if (IS_ERR(entry))
                        return (struct lttng_ust_tracepoint_probe *)entry;
This page took 0.027558 seconds and 4 git commands to generate.