Fix: RCU read-side lock released too early in destroy_agent_app
[lttng-tools.git] / src / bin / lttng-sessiond / agent.c
index cf8264a307b7029f479b779dd846221212922567..1eb64c25e32b937282bd5f1b45c7442d3909b188 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #define _GNU_SOURCE
+#define _LGPL_SOURCE
 #include <assert.h>
 #include <urcu/uatomic.h>
 
@@ -452,7 +453,8 @@ int agent_send_registration_done(struct agent_app *app)
  *
  * Return LTTNG_OK on success or else a LTTNG_ERR* code.
  */
-int agent_enable_event(struct agent_event *event)
+int agent_enable_event(struct agent_event *event,
+               enum lttng_domain_type domain)
 {
        int ret;
        struct agent_app *app;
@@ -464,6 +466,10 @@ int agent_enable_event(struct agent_event *event)
 
        cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app,
                        node.node) {
+               if (app->domain != domain) {
+                       continue;
+               }
+
                /* Enable event on agent application through TCP socket. */
                ret = enable_event(app, event);
                if (ret != LTTNG_OK) {
@@ -485,7 +491,8 @@ error:
  *
  * Return LTTNG_OK on success or else a LTTNG_ERR* code.
  */
-int agent_disable_event(struct agent_event *event)
+int agent_disable_event(struct agent_event *event,
+               enum lttng_domain_type domain)
 {
        int ret;
        struct agent_app *app;
@@ -497,6 +504,10 @@ int agent_disable_event(struct agent_event *event)
 
        cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app,
                        node.node) {
+               if (app->domain != domain) {
+                       continue;
+               }
+
                /* Enable event on agent application through TCP socket. */
                ret = disable_event(app, event);
                if (ret != LTTNG_OK) {
@@ -518,7 +529,8 @@ error:
  *
  * Return the number of events or else a negative value.
  */
-int agent_list_events(struct lttng_event **events)
+int agent_list_events(struct lttng_event **events,
+               enum lttng_domain_type domain)
 {
        int ret;
        size_t nbmem, count = 0;
@@ -528,6 +540,8 @@ int agent_list_events(struct lttng_event **events)
 
        assert(events);
 
+       DBG2("Agent listing events for domain %d", domain);
+
        nbmem = UST_APP_EVENT_LIST_SIZE;
        tmp_events = zmalloc(nbmem * sizeof(*tmp_events));
        if (!tmp_events) {
@@ -542,6 +556,11 @@ int agent_list_events(struct lttng_event **events)
                ssize_t nb_ev;
                struct lttng_event *agent_events;
 
+               /* Skip domain not asked by the list. */
+               if (app->domain != domain) {
+                       continue;
+               }
+
                nb_ev = list_events(app, &agent_events);
                if (nb_ev < 0) {
                        ret = nb_ev;
@@ -593,7 +612,8 @@ error:
  *
  * Return newly allocated object or else NULL on error.
  */
-struct agent_app *agent_create_app(pid_t pid, struct lttcomm_sock *sock)
+struct agent_app *agent_create_app(pid_t pid, enum lttng_domain_type domain,
+               struct lttcomm_sock *sock)
 {
        struct agent_app *app;
 
@@ -606,6 +626,7 @@ struct agent_app *agent_create_app(pid_t pid, struct lttcomm_sock *sock)
        }
 
        app->pid = pid;
+       app->domain = domain;
        app->sock = sock;
        lttng_ht_node_init_ulong(&app->node, (unsigned long) app->sock->fd);
 
@@ -659,6 +680,8 @@ void agent_add_app(struct agent_app *app)
 
 /*
  * Delete agent application from the global hash table.
+ *
+ * rcu_read_lock() must be held by the caller.
  */
 void agent_delete_app(struct agent_app *app)
 {
@@ -670,9 +693,7 @@ void agent_delete_app(struct agent_app *app)
        DBG3("Agent deleting app pid: %d and sock: %d", app->pid, app->sock->fd);
 
        iter.iter.node = &app->node.node;
-       rcu_read_lock();
        ret = lttng_ht_del(agent_apps_ht_by_sock, &iter);
-       rcu_read_unlock();
        assert(!ret);
 }
 
@@ -709,6 +730,7 @@ int agent_init(struct agent *agt)
                ret = -ENOMEM;
                goto error;
        }
+       lttng_ht_node_init_u64(&agt->node, agt->domain);
 
        return 0;
 
@@ -716,6 +738,48 @@ error:
        return ret;
 }
 
+/*
+ * Add agent object to the given hash table.
+ */
+void agent_add(struct agent *agt, struct lttng_ht *ht)
+{
+       assert(agt);
+       assert(ht);
+
+       DBG3("Agent adding from domain %d", agt->domain);
+
+       rcu_read_lock();
+       lttng_ht_add_unique_u64(ht, &agt->node);
+       rcu_read_unlock();
+}
+
+/*
+ * Create an agent object for the given domain.
+ *
+ * Return the allocated agent or NULL on error.
+ */
+struct agent *agent_create(enum lttng_domain_type domain)
+{
+       int ret;
+       struct agent *agt;
+
+       agt = zmalloc(sizeof(*agt));
+       if (!agt) {
+               goto error;
+       }
+       agt->domain = domain;
+
+       ret = agent_init(agt);
+       if (ret < 0) {
+               free(agt);
+               agt = NULL;
+               goto error;
+       }
+
+error:
+       return agt;
+}
+
 /*
  * Create a newly allocated agent event data structure. If name is valid, it's
  * copied into the created event.
@@ -836,7 +900,7 @@ struct agent_event *agent_find_event(const char *name, int loglevel,
        return caa_container_of(node, struct agent_event, node);
 
 error:
-       DBG3("Agent NOT found %s.", name);
+       DBG3("Agent event NOT found %s.", name);
        return NULL;
 }
 
@@ -849,6 +913,7 @@ void agent_destroy_event(struct agent_event *event)
 {
        assert(event);
 
+       free(event->filter);
        free(event);
 }
 
@@ -892,7 +957,7 @@ void agent_destroy(struct agent *agt)
        }
        rcu_read_unlock();
 
-       lttng_ht_destroy(agt->events);
+       ht_cleanup_push(agt->events);
 }
 
 /*
This page took 0.026021 seconds and 4 git commands to generate.