Fix: stream fd leaks on error
[lttng-ust.git] / liblttng-ust / lttng-ust-comm.c
index de03407b702aa5851f7fc69ae99633f5f08455f4..708b9192f22b62b14985f8d7ffa3c7d423813d2d 100644 (file)
@@ -39,8 +39,9 @@
 #include <signal.h>
 #include <limits.h>
 #include <urcu/uatomic.h>
-#include <urcu/futex.h>
+#include "futex.h"
 #include <urcu/compiler.h>
+#include <lttng/urcu/urcu-ust.h>
 
 #include <lttng/align.h>
 #include <lttng/ust-events.h>
@@ -350,6 +351,13 @@ static const char *cmd_name_mapping[] = {
 
        /* Event notifier group commands */
        [ LTTNG_UST_EVENT_NOTIFIER_CREATE ] = "Create event notifier",
+
+       /* Session and event notifier group commands */
+       [ LTTNG_UST_COUNTER ] = "Create Counter",
+
+       /* Counter commands */
+       [ LTTNG_UST_COUNTER_GLOBAL ] = "Create Counter Global",
+       [ LTTNG_UST_COUNTER_CPU ] = "Create Counter CPU",
 };
 
 static const char *str_timeout;
@@ -365,6 +373,10 @@ extern void lttng_ring_buffer_client_overwrite_rt_exit(void);
 extern void lttng_ring_buffer_client_discard_exit(void);
 extern void lttng_ring_buffer_client_discard_rt_exit(void);
 extern void lttng_ring_buffer_metadata_client_exit(void);
+extern void lttng_counter_client_percpu_32_modular_init(void);
+extern void lttng_counter_client_percpu_32_modular_exit(void);
+extern void lttng_counter_client_percpu_64_modular_init(void);
+extern void lttng_counter_client_percpu_64_modular_exit(void);
 
 static char *get_map_shm(struct sock_info *sock_info);
 
@@ -423,8 +435,7 @@ void lttng_fixup_ust_mutex_nest_tls(void)
 static
 void lttng_fixup_urcu_bp_tls(void)
 {
-       rcu_read_lock();
-       rcu_read_unlock();
+       (void) lttng_ust_urcu_read_ongoing();
 }
 
 void lttng_ust_fixup_tls(void)
@@ -1054,10 +1065,23 @@ int handle_message(struct sock_info *sock_info,
                                        &args, sock_info);
                else
                        ret = -ENOSYS;
+               if (args.channel.wakeup_fd >= 0) {
+                       int close_ret;
+
+                       lttng_ust_lock_fd_tracker();
+                       close_ret = close(args.channel.wakeup_fd);
+                       lttng_ust_unlock_fd_tracker();
+                       args.channel.wakeup_fd = -1;
+                       if (close_ret)
+                               PERROR("close");
+               }
+               free(args.channel.chan_data);
                break;
        }
        case LTTNG_UST_STREAM:
        {
+               int close_ret;
+
                /* Receive shm_fd, wakeup_fd */
                ret = ustcomm_recv_stream_from_sessiond(sock,
                        NULL,
@@ -1073,6 +1097,22 @@ int handle_message(struct sock_info *sock_info,
                                        &args, sock_info);
                else
                        ret = -ENOSYS;
+               if (args.stream.shm_fd >= 0) {
+                       lttng_ust_lock_fd_tracker();
+                       close_ret = close(args.stream.shm_fd);
+                       lttng_ust_unlock_fd_tracker();
+                       args.stream.shm_fd = -1;
+                       if (close_ret)
+                               PERROR("close");
+               }
+               if (args.stream.wakeup_fd >= 0) {
+                       lttng_ust_lock_fd_tracker();
+                       close_ret = close(args.stream.wakeup_fd);
+                       lttng_ust_unlock_fd_tracker();
+                       args.stream.wakeup_fd = -1;
+                       if (close_ret)
+                               PERROR("close");
+               }
                break;
        }
        case LTTNG_UST_CONTEXT:
@@ -1133,6 +1173,121 @@ int handle_message(struct sock_info *sock_info,
                        ret = -ENOSYS;
                }
                break;
+       case LTTNG_UST_COUNTER:
+       {
+               void *counter_data;
+
+               len = ustcomm_recv_counter_from_sessiond(sock,
+                               &counter_data, lum->u.counter.len);
+               switch (len) {
+               case 0: /* orderly shutdown */
+                       ret = 0;
+                       goto error;
+               default:
+                       if (len == lum->u.counter.len) {
+                               DBG("counter data received");
+                               break;
+                       } else if (len < 0) {
+                               DBG("Receive failed from lttng-sessiond with errno %d", (int) -len);
+                               if (len == -ECONNRESET) {
+                                       ERR("%s remote end closed connection", sock_info->name);
+                                       ret = len;
+                                       goto error;
+                               }
+                               ret = len;
+                               goto error;
+                       } else {
+                               DBG("incorrect counter data message size: %zd", len);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+               }
+               args.counter.counter_data = counter_data;
+               if (ops->cmd)
+                       ret = ops->cmd(lum->handle, lum->cmd,
+                                       (unsigned long) &lum->u,
+                                       &args, sock_info);
+               else
+                       ret = -ENOSYS;
+               break;
+       }
+       case LTTNG_UST_COUNTER_GLOBAL:
+       {
+               /* Receive shm_fd */
+               ret = ustcomm_recv_counter_shm_from_sessiond(sock,
+                       &args.counter_shm.shm_fd);
+               if (ret) {
+                       goto error;
+               }
+
+               if (ops->cmd)
+                       ret = ops->cmd(lum->handle, lum->cmd,
+                                       (unsigned long) &lum->u,
+                                       &args, sock_info);
+               else
+                       ret = -ENOSYS;
+               break;
+       }
+       case LTTNG_UST_COUNTER_CPU:
+       {
+               /* Receive shm_fd */
+               ret = ustcomm_recv_counter_shm_from_sessiond(sock,
+                       &args.counter_shm.shm_fd);
+               if (ret) {
+                       goto error;
+               }
+
+               if (ops->cmd)
+                       ret = ops->cmd(lum->handle, lum->cmd,
+                                       (unsigned long) &lum->u,
+                                       &args, sock_info);
+               else
+                       ret = -ENOSYS;
+               break;
+       }
+       case LTTNG_UST_EVENT_NOTIFIER_CREATE:
+       {
+               /* Receive struct lttng_ust_event_notifier */
+               struct lttng_ust_event_notifier event_notifier;
+
+               if (sizeof(event_notifier) != lum->u.event_notifier.len) {
+                       DBG("incorrect event notifier data message size: %u", lum->u.event_notifier.len);
+                       ret = -EINVAL;
+                       goto error;
+               }
+               len = ustcomm_recv_unix_sock(sock, &event_notifier, sizeof(event_notifier));
+               switch (len) {
+               case 0: /* orderly shutdown */
+                       ret = 0;
+                       goto error;
+               default:
+                       if (len == sizeof(event_notifier)) {
+                               DBG("event notifier data received");
+                               break;
+                       } else if (len < 0) {
+                               DBG("Receive failed from lttng-sessiond with errno %d", (int) -len);
+                               if (len == -ECONNRESET) {
+                                       ERR("%s remote end closed connection", sock_info->name);
+                                       ret = len;
+                                       goto error;
+                               }
+                               ret = len;
+                               goto error;
+                       } else {
+                               DBG("incorrect event notifier data message size: %zd", len);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+               }
+               if (ops->cmd)
+                       ret = ops->cmd(lum->handle, lum->cmd,
+                                       (unsigned long) &event_notifier,
+                                       &args, sock_info);
+               else
+                       ret = -ENOSYS;
+               break;
+       }
+
        default:
                if (ops->cmd)
                        ret = ops->cmd(lum->handle, lum->cmd,
@@ -1540,7 +1695,7 @@ void wait_for_sessiond(struct sock_info *sock_info)
        if (uatomic_read((int32_t *) sock_info->wait_shm_mmap))
                goto end_wait;
 
-       while (futex_async((int32_t *) sock_info->wait_shm_mmap,
+       while (lttng_ust_futex_async((int32_t *) sock_info->wait_shm_mmap,
                        FUTEX_WAIT, 0, NULL, NULL, 0)) {
                switch (errno) {
                case EWOULDBLOCK:
@@ -1958,6 +2113,8 @@ void __attribute__((constructor)) lttng_ust_init(void)
        lttng_ring_buffer_client_overwrite_rt_init();
        lttng_ring_buffer_client_discard_init();
        lttng_ring_buffer_client_discard_rt_init();
+       lttng_counter_client_percpu_32_modular_init();
+       lttng_counter_client_percpu_64_modular_init();
        lttng_perf_counter_init();
        /*
         * Invoke ust malloc wrapper init before starting other threads.
@@ -2103,6 +2260,8 @@ void lttng_ust_cleanup(int exiting)
        lttng_ring_buffer_client_overwrite_rt_exit();
        lttng_ring_buffer_client_overwrite_exit();
        lttng_ring_buffer_metadata_client_exit();
+       lttng_counter_client_percpu_32_modular_exit();
+       lttng_counter_client_percpu_64_modular_exit();
        lttng_ust_statedump_destroy();
        exit_tracepoint();
        if (!exiting) {
@@ -2227,7 +2386,9 @@ void ust_before_fork(sigset_t *save_sigset)
        pthread_mutex_lock(&ust_fork_mutex);
 
        ust_lock_nocheck();
-       urcu_bp_before_fork();
+       lttng_ust_urcu_before_fork();
+       if (lttng_ust_liburcu_bp_before_fork)
+               lttng_ust_liburcu_bp_before_fork();
        lttng_ust_lock_fd_tracker();
        lttng_perf_lock();
 }
@@ -2255,7 +2416,9 @@ void ust_after_fork_parent(sigset_t *restore_sigset)
        if (URCU_TLS(lttng_ust_nest_count))
                return;
        DBG("process %d", getpid());
-       urcu_bp_after_fork_parent();
+       lttng_ust_urcu_after_fork_parent();
+       if (lttng_ust_liburcu_bp_after_fork_parent)
+               lttng_ust_liburcu_bp_after_fork_parent();
        /* Release mutexes and reenable signals */
        ust_after_fork_common(restore_sigset);
 }
@@ -2281,7 +2444,9 @@ void ust_after_fork_child(sigset_t *restore_sigset)
        ust_context_vgids_reset();
        DBG("process %d", getpid());
        /* Release urcu mutexes */
-       urcu_bp_after_fork_child();
+       lttng_ust_urcu_after_fork_child();
+       if (lttng_ust_liburcu_bp_after_fork_child)
+               lttng_ust_liburcu_bp_after_fork_child();
        lttng_ust_cleanup(0);
        /* Release mutexes and reenable signals */
        ust_after_fork_common(restore_sigset);
This page took 0.026482 seconds and 4 git commands to generate.