Fix: wrong check after malloc in buffer registry
[lttng-tools.git] / src / bin / lttng-sessiond / buffer-registry.c
index 765294fa4ca33f11fe9b4f331a3c46e4e3bb0ac3..e64e4375ed139ab0c51d2f300a6dd47b96a4ebfc 100644 (file)
@@ -25,6 +25,7 @@
 #include "fd-limit.h"
 #include "ust-consumer.h"
 #include "ust-ctl.h"
+#include "utils.h"
 
 /*
  * Set in main.c during initialization process of the daemon. This contains
@@ -119,7 +120,7 @@ int buffer_reg_uid_create(int session_id, uint32_t bits_per_long, uid_t uid,
        }
 
        reg->registry = zmalloc(sizeof(struct buffer_reg_session));
-       if (!reg) {
+       if (!reg->registry) {
                PERROR("zmalloc buffer registry uid session");
                ret = -ENOMEM;
                goto error;
@@ -239,7 +240,7 @@ int buffer_reg_pid_create(int session_id, struct buffer_reg_pid **regp)
        }
 
        reg->registry = zmalloc(sizeof(struct buffer_reg_session));
-       if (!reg) {
+       if (!reg->registry) {
                PERROR("zmalloc buffer registry pid session");
                ret = -ENOMEM;
                goto error;
@@ -492,8 +493,7 @@ void buffer_reg_channel_destroy(struct buffer_reg_channel *regp,
                return;
        }
 
-       DBG3("Buffer registry channel destroy with key %" PRIu32 " and handle %d",
-                       regp->key, regp->obj.ust->handle);
+       DBG3("Buffer registry channel destroy with key %" PRIu32, regp->key);
 
        switch (domain) {
        case LTTNG_DOMAIN_UST:
@@ -506,12 +506,14 @@ void buffer_reg_channel_destroy(struct buffer_reg_channel *regp,
                        buffer_reg_stream_destroy(sreg, domain);
                }
 
-               ret = ust_ctl_release_object(-1, regp->obj.ust);
-               if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
-                       ERR("Buffer reg channel release obj handle %d failed with ret %d",
-                                       regp->obj.ust->handle, ret);
+               if (regp->obj.ust) {
+                       ret = ust_ctl_release_object(-1, regp->obj.ust);
+                       if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
+                               ERR("Buffer reg channel release obj handle %d failed with ret %d",
+                                               regp->obj.ust->handle, ret);
+                       }
+                       free(regp->obj.ust);
                }
-               free(regp->obj.ust);
                lttng_fd_put(LTTNG_FD_APPS, 1);
                break;
        }
@@ -525,8 +527,10 @@ void buffer_reg_channel_destroy(struct buffer_reg_channel *regp,
 
 /*
  * Destroy a buffer registry session with the given domain.
+ *
+ * Should *NOT* be called with RCU read-side lock held.
  */
-void buffer_reg_session_destroy(struct buffer_reg_session *regp,
+static void buffer_reg_session_destroy(struct buffer_reg_session *regp,
                enum lttng_domain_type domain)
 {
        int ret;
@@ -543,9 +547,10 @@ void buffer_reg_session_destroy(struct buffer_reg_session *regp,
                assert(!ret);
                buffer_reg_channel_destroy(reg_chan, domain);
        }
-       lttng_ht_destroy(regp->channels);
        rcu_read_unlock();
 
+       ht_cleanup_push(regp->channels);
+
        switch (domain) {
        case LTTNG_DOMAIN_UST:
                ust_registry_session_destroy(regp->reg.ust);
@@ -560,8 +565,7 @@ void buffer_reg_session_destroy(struct buffer_reg_session *regp,
 }
 
 /*
- * Remove buffer registry UID object from the global hash table. RCU read side
- * lock MUST be acquired before calling this.
+ * Remove buffer registry UID object from the global hash table.
  */
 void buffer_reg_uid_remove(struct buffer_reg_uid *regp)
 {
@@ -570,9 +574,11 @@ void buffer_reg_uid_remove(struct buffer_reg_uid *regp)
 
        assert(regp);
 
+       rcu_read_lock();
        iter.iter.node = &regp->node.node;
        ret = lttng_ht_del(buffer_registry_uid, &iter);
        assert(!ret);
+       rcu_read_unlock();
 }
 
 static void rcu_free_buffer_reg_uid(struct rcu_head *head)
@@ -618,11 +624,12 @@ void buffer_reg_uid_destroy(struct buffer_reg_uid *regp,
                goto destroy;
        }
 
+       rcu_read_lock();
        /* Get the right socket from the consumer object. */
        socket = consumer_find_socket_by_bitness(regp->bits_per_long,
                        consumer);
        if (!socket) {
-               goto destroy;
+               goto unlock;
        }
 
        switch (regp->domain) {
@@ -635,9 +642,12 @@ void buffer_reg_uid_destroy(struct buffer_reg_uid *regp,
                break;
        default:
                assert(0);
+               rcu_read_unlock();
                return;
        }
 
+unlock:
+       rcu_read_unlock();
 destroy:
        call_rcu(&regp->node.head, rcu_free_buffer_reg_uid);
 }
@@ -677,10 +687,12 @@ void buffer_reg_pid_destroy(struct buffer_reg_pid *regp)
 
 /*
  * Destroy per PID and UID registry hash table.
+ *
+ * Should *NOT* be called with RCU read-side lock held.
  */
 void buffer_reg_destroy_registries(void)
 {
        DBG3("Buffer registry destroy all registry");
-       lttng_ht_destroy(buffer_registry_uid);
-       lttng_ht_destroy(buffer_registry_pid);
+       ht_cleanup_push(buffer_registry_uid);
+       ht_cleanup_push(buffer_registry_pid);
 }
This page took 0.025276 seconds and 4 git commands to generate.