Fix: hash table cleanup call_rcu deadlock
[lttng-tools.git] / src / bin / lttng-sessiond / ust-registry.c
index 7250dd12d751b0edcce93ffd4b886f8bdd7c7395..6e9f0699b334bbeebb00957b0e9a9b0bd486ea1b 100644 (file)
@@ -23,6 +23,7 @@
 #include <lttng/lttng.h>
 
 #include "ust-registry.h"
+#include "utils.h"
 
 /*
  * Hash table match function for event in the registry.
@@ -310,9 +311,9 @@ void ust_registry_destroy_event(struct ust_registry_channel *chan,
 
 /*
  * We need to execute ht_destroy outside of RCU read-side critical
- * section, so we postpone its execution using call_rcu. It is simpler
- * than to change the semantic of the many callers of
- * destroy_channel().
+ * section and outside of call_rcu thread, so we postpone its execution
+ * using ht_cleanup_push. It is simpler than to change the semantic of
+ * the many callers of delete_ust_app_session().
  */
 static
 void destroy_channel_rcu(struct rcu_head *head)
@@ -320,7 +321,9 @@ void destroy_channel_rcu(struct rcu_head *head)
        struct ust_registry_channel *chan =
                caa_container_of(head, struct ust_registry_channel, rcu_head);
 
-       lttng_ht_destroy(chan->ht);
+       if (chan->ht) {
+               ht_cleanup_push(chan->ht);
+       }
        free(chan);
 }
 
@@ -361,7 +364,7 @@ int ust_registry_channel_add(struct ust_registry_session *session,
        if (!chan) {
                PERROR("zmalloc ust registry channel");
                ret = -ENOMEM;
-               goto error;
+               goto error_alloc;
        }
 
        chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
@@ -390,7 +393,11 @@ int ust_registry_channel_add(struct ust_registry_session *session,
        lttng_ht_add_unique_u64(session->channels, &chan->node);
        rcu_read_unlock();
 
+       return 0;
+
 error:
+       destroy_channel(chan);
+error_alloc:
        return ret;
 }
 
@@ -480,7 +487,7 @@ int ust_registry_session_init(struct ust_registry_session **sessionp,
        session = zmalloc(sizeof(*session));
        if (!session) {
                PERROR("zmalloc ust registry session");
-               goto error;
+               goto error_alloc;
        }
 
        pthread_mutex_init(&session->lock, NULL);
@@ -516,6 +523,8 @@ int ust_registry_session_init(struct ust_registry_session **sessionp,
        return 0;
 
 error:
+       ust_registry_session_destroy(session);
+error_alloc:
        return -1;
 }
 
@@ -543,6 +552,8 @@ void ust_registry_session_destroy(struct ust_registry_session *reg)
        }
        rcu_read_unlock();
 
-       lttng_ht_destroy(reg->channels);
+       if (reg->channels) {
+               ht_cleanup_push(reg->channels);
+       }
        free(reg->metadata);
 }
This page took 0.025826 seconds and 5 git commands to generate.