Introduce file descriptor tracker
[lttng-ust.git] / liblttng-ust / lttng-ust-comm.c
index 6105403a25d032b618df9c6202644ff138a0a034..4a21866358b66a4d9f766abdfd47665e2cffe13d 100644 (file)
@@ -46,6 +46,7 @@
 #include <lttng/ust-ctl.h>
 #include <urcu/tls-compat.h>
 #include <ust-comm.h>
+#include <ust-fd.h>
 #include <usterr-signal-safe.h>
 #include <helper.h>
 #include "tracepoint-internal.h"
@@ -106,6 +107,14 @@ static pthread_mutex_t ust_fork_mutex = PTHREAD_MUTEX_INITIALIZER;
 /* Should the ust comm thread quit ? */
 static int lttng_ust_comm_should_quit;
 
+/*
+ * This variable can be tested by applications to check whether
+ * lttng-ust is loaded. They simply have to define their own
+ * "lttng_ust_loaded" weak symbol, and test it. It is set to 1 by the
+ * library constructor.
+ */
+int lttng_ust_loaded __attribute__((weak));
+
 /*
  * Return 0 on success, -1 if should quit.
  * The lock is taken in both cases.
@@ -388,6 +397,17 @@ void lttng_fixup_urcu_bp_tls(void)
        rcu_read_unlock();
 }
 
+void lttng_ust_fixup_tls(void)
+{
+       lttng_fixup_urcu_bp_tls();
+       lttng_fixup_ringbuffer_tls();
+       lttng_fixup_vtid_tls();
+       lttng_fixup_nest_count_tls();
+       lttng_fixup_procname_tls();
+       lttng_fixup_ust_mutex_nest_tls();
+       lttng_ust_fixup_fd_tracker_tls();
+}
+
 int lttng_get_notify_socket(void *owner)
 {
        struct sock_info *info = owner;
@@ -441,7 +461,7 @@ int setup_local_apps(void)
 }
 
 /*
- * Get notify_sock timeout, in ms.
+ * Get socket timeout, in ms.
  * -1: wait forever. 0: don't wait. >0: timeout, in ms.
  */
 static
@@ -461,12 +481,20 @@ long get_timeout(void)
        return constructor_delay_ms;
 }
 
+/* Timeout for notify socket send and recv. */
 static
 long get_notify_sock_timeout(void)
 {
        return get_timeout();
 }
 
+/* Timeout for connecting to cmd and notify sockets. */
+static
+long get_connect_sock_timeout(void)
+{
+       return get_timeout();
+}
+
 /*
  * Return values: -1: wait forever. 0: don't wait. 1: timeout wait.
  */
@@ -1205,17 +1233,28 @@ char *get_map_shm(struct sock_info *sock_info)
                goto error;
        }
 
+       lttng_ust_lock_fd_tracker();
        wait_shm_fd = get_wait_shm(sock_info, page_size);
        if (wait_shm_fd < 0) {
+               lttng_ust_unlock_fd_tracker();
                goto error;
        }
+       lttng_ust_add_fd_to_tracker(wait_shm_fd);
+       lttng_ust_unlock_fd_tracker();
+
        wait_shm_mmap = mmap(NULL, page_size, PROT_READ,
                  MAP_SHARED, wait_shm_fd, 0);
+
        /* close shm fd immediately after taking the mmap reference */
+       lttng_ust_lock_fd_tracker();
        ret = close(wait_shm_fd);
-       if (ret) {
+       if (!ret) {
+               lttng_ust_delete_fd_from_tracker(wait_shm_fd);
+       } else {
                PERROR("Error closing fd");
        }
+       lttng_ust_unlock_fd_tracker();
+
        if (wait_shm_mmap == MAP_FAILED) {
                DBG("mmap error (can be caused by race with sessiond). Fallback to poll mode.");
                goto error;
@@ -1295,6 +1334,7 @@ void *ust_listener_thread(void *arg)
        int sock, ret, prev_connect_failed = 0, has_waited = 0;
        long timeout;
 
+       lttng_ust_fixup_tls();
        /*
         * If available, add '-ust' to the end of this thread's
         * process name
@@ -1324,6 +1364,7 @@ restart:
        }
 
        if (sock_info->socket != -1) {
+               /* FD tracker is updated by ustcomm_close_unix_sock() */
                ret = ustcomm_close_unix_sock(sock_info->socket);
                if (ret) {
                        ERR("Error closing %s ust cmd socket",
@@ -1332,6 +1373,7 @@ restart:
                sock_info->socket = -1;
        }
        if (sock_info->notify_socket != -1) {
+               /* FD tracker is updated by ustcomm_close_unix_sock() */
                ret = ustcomm_close_unix_sock(sock_info->notify_socket);
                if (ret) {
                        ERR("Error closing %s ust notify socket",
@@ -1340,6 +1382,10 @@ restart:
                sock_info->notify_socket = -1;
        }
 
+       if (ust_lock()) {
+               goto quit;
+       }
+
        /*
         * Register. We need to perform both connect and sending
         * registration message before doing the next connect otherwise
@@ -1348,15 +1394,14 @@ restart:
         * first connect registration message.
         */
        /* Connect cmd socket */
-       ret = ustcomm_connect_unix_sock(sock_info->sock_path);
+       lttng_ust_lock_fd_tracker();
+       ret = ustcomm_connect_unix_sock(sock_info->sock_path,
+               get_connect_sock_timeout());
        if (ret < 0) {
+               lttng_ust_unlock_fd_tracker();
                DBG("Info: sessiond not accepting connections to %s apps socket", sock_info->name);
                prev_connect_failed = 1;
 
-               if (ust_lock()) {
-                       goto quit;
-               }
-
                /*
                 * If we cannot find the sessiond daemon, don't delay
                 * constructor execution.
@@ -1366,8 +1411,16 @@ restart:
                ust_unlock();
                goto restart;
        }
+       lttng_ust_add_fd_to_tracker(ret);
+       lttng_ust_unlock_fd_tracker();
        sock_info->socket = ret;
 
+       ust_unlock();
+       /*
+        * Unlock/relock ust lock because connect is blocking (with
+        * timeout). Don't delay constructors on the ust lock for too
+        * long.
+        */
        if (ust_lock()) {
                goto quit;
        }
@@ -1402,17 +1455,24 @@ restart:
        }
 
        ust_unlock();
+       /*
+        * Unlock/relock ust lock because connect is blocking (with
+        * timeout). Don't delay constructors on the ust lock for too
+        * long.
+        */
+       if (ust_lock()) {
+               goto quit;
+       }
 
        /* Connect notify socket */
-       ret = ustcomm_connect_unix_sock(sock_info->sock_path);
+       lttng_ust_lock_fd_tracker();
+       ret = ustcomm_connect_unix_sock(sock_info->sock_path,
+               get_connect_sock_timeout());
        if (ret < 0) {
+               lttng_ust_unlock_fd_tracker();
                DBG("Info: sessiond not accepting connections to %s apps socket", sock_info->name);
                prev_connect_failed = 1;
 
-               if (ust_lock()) {
-                       goto quit;
-               }
-
                /*
                 * If we cannot find the sessiond daemon, don't delay
                 * constructor execution.
@@ -1422,8 +1482,20 @@ restart:
                ust_unlock();
                goto restart;
        }
+       lttng_ust_add_fd_to_tracker(ret);
+       lttng_ust_unlock_fd_tracker();
        sock_info->notify_socket = ret;
 
+       ust_unlock();
+       /*
+        * Unlock/relock ust lock because connect is blocking (with
+        * timeout). Don't delay constructors on the ust lock for too
+        * long.
+        */
+       if (ust_lock()) {
+               goto quit;
+       }
+
        timeout = get_notify_sock_timeout();
        if (timeout >= 0) {
                /*
@@ -1446,10 +1518,6 @@ restart:
                WARN("Unsupported timeout value %ld", timeout);
        }
 
-       if (ust_lock()) {
-               goto quit;
-       }
-
        ret = register_to_sessiond(sock_info->notify_socket,
                        USTCTL_SOCKET_NOTIFY);
        if (ret < 0) {
@@ -1567,12 +1635,9 @@ void __attribute__((constructor)) lttng_ust_init(void)
         * to be the dynamic linker mutex) and ust_lock, taken within
         * the ust lock.
         */
-       lttng_fixup_urcu_bp_tls();
-       lttng_fixup_ringbuffer_tls();
-       lttng_fixup_vtid_tls();
-       lttng_fixup_nest_count_tls();
-       lttng_fixup_procname_tls();
-       lttng_fixup_ust_mutex_nest_tls();
+       lttng_ust_fixup_tls();
+
+       lttng_ust_loaded = 1;
 
        /*
         * We want precise control over the order in which we construct
@@ -1582,6 +1647,7 @@ void __attribute__((constructor)) lttng_ust_init(void)
         */
        init_usterr();
        init_tracepoint();
+       lttng_ust_init_fd_tracker();
        lttng_ust_clock_init();
        lttng_ust_getcpu_init();
        lttng_ust_statedump_init();
@@ -1705,6 +1771,7 @@ void lttng_ust_cleanup(int exiting)
 {
        cleanup_sock_info(&global_apps, exiting);
        cleanup_sock_info(&local_apps, exiting);
+       local_apps.allowed = 0;
        /*
         * The teardown in this function all affect data structures
         * accessed under the UST lock by the listener thread. This
@@ -1800,6 +1867,9 @@ void ust_before_fork(sigset_t *save_sigset)
        sigset_t all_sigs;
        int ret;
 
+       /* Fixup lttng-ust TLS. */
+       lttng_ust_fixup_tls();
+
        if (URCU_TLS(lttng_ust_nest_count))
                return;
        /* Disable signals */
@@ -1854,11 +1924,11 @@ void ust_after_fork_child(sigset_t *restore_sigset)
 {
        if (URCU_TLS(lttng_ust_nest_count))
                return;
+       lttng_context_vtid_reset();
        DBG("process %d", getpid());
        /* Release urcu mutexes */
        rcu_bp_after_fork_child();
        lttng_ust_cleanup(0);
-       lttng_context_vtid_reset();
        /* Release mutexes and reenable signals */
        ust_after_fork_common(restore_sigset);
        lttng_ust_init();
This page took 0.025684 seconds and 4 git commands to generate.