Use ust_lock during sock_info operations for atomicity against fork
[lttng-ust.git] / liblttng-ust / lttng-ust-comm.c
index dd8822cf13138a22053a7f04c2a143cbde556ad1..0cf5ecd9687536be5fc7794c4bfeb28ed135a11f 100644 (file)
@@ -35,6 +35,7 @@
 #include <time.h>
 #include <assert.h>
 #include <signal.h>
+#include <limits.h>
 #include <urcu/uatomic.h>
 #include <urcu/futex.h>
 #include <urcu/compiler.h>
 #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"
 #include "lttng-tracer-core.h"
 #include "compat.h"
-#include "../libringbuffer/tlsfixup.h"
+#include "../libringbuffer/rb-init.h"
 #include "lttng-ust-statedump.h"
 #include "clock.h"
 #include "../libringbuffer/getcpu.h"
@@ -364,11 +366,11 @@ const char *get_lttng_home_dir(void)
 {
        const char *val;
 
-       val = (const char *) lttng_secure_getenv("LTTNG_HOME");
+       val = (const char *) lttng_getenv("LTTNG_HOME");
        if (val != NULL) {
                return val;
        }
-       return (const char *) lttng_secure_getenv("HOME");
+       return (const char *) lttng_getenv("HOME");
 }
 
 /*
@@ -404,6 +406,7 @@ void lttng_ust_fixup_tls(void)
        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)
@@ -468,7 +471,7 @@ long get_timeout(void)
        long constructor_delay_ms = LTTNG_UST_DEFAULT_CONSTRUCTOR_TIMEOUT_MS;
 
        if (!got_timeout_env) {
-               str_timeout = getenv("LTTNG_UST_REGISTER_TIMEOUT");
+               str_timeout = lttng_getenv("LTTNG_UST_REGISTER_TIMEOUT");
                got_timeout_env = 1;
        }
        if (str_timeout)
@@ -531,6 +534,19 @@ int get_constructor_timeout(struct timespec *constructor_timeout)
        return 1;
 }
 
+static
+void get_allow_blocking(void)
+{
+       const char *str_allow_blocking =
+               lttng_getenv("LTTNG_UST_ALLOW_BLOCKING");
+
+       if (str_allow_blocking) {
+               DBG("%s environment variable is set",
+                       "LTTNG_UST_ALLOW_BLOCKING");
+               lttng_ust_ringbuffer_set_allow_blocking();
+       }
+}
+
 static
 int register_to_sessiond(int socket, enum ustctl_socket_type type)
 {
@@ -954,6 +970,21 @@ int handle_message(struct sock_info *sock_info,
                }
        }
        DBG("Return value: %d", lur.ret_val);
+
+       ust_unlock();
+
+       /*
+        * Performed delayed statedump operations outside of the UST
+        * lock. We need to take the dynamic loader lock before we take
+        * the UST lock internally within handle_pending_statedump().
+         */
+       handle_pending_statedump(sock_info);
+
+       if (ust_lock()) {
+               ret = -LTTNG_UST_ERR_EXITING;
+               goto error;
+       }
+
        ret = send_reply(sock, &lur);
        if (ret < 0) {
                DBG("error sending reply");
@@ -984,13 +1015,6 @@ int handle_message(struct sock_info *sock_info,
 error:
        ust_unlock();
 
-       /*
-        * Performed delayed statedump operations outside of the UST
-        * lock. We need to take the dynamic loader lock before we take
-        * the UST lock internally within handle_pending_statedump().
-         */
-       handle_pending_statedump(sock_info);
-
        return ret;
 }
 
@@ -1231,17 +1255,39 @@ 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;
+       }
+
+       ret = lttng_ust_add_fd_to_tracker(wait_shm_fd);
+       if (ret < 0) {
+               ret = close(wait_shm_fd);
+               if (!ret) {
+                       PERROR("Error closing fd");
+               }
+               lttng_ust_unlock_fd_tracker();
                goto error;
        }
+
+       wait_shm_fd = ret;
+       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;
@@ -1318,7 +1364,7 @@ static
 void *ust_listener_thread(void *arg)
 {
        struct sock_info *sock_info = arg;
-       int sock, ret, prev_connect_failed = 0, has_waited = 0;
+       int sock, ret, prev_connect_failed = 0, has_waited = 0, fd;
        long timeout;
 
        lttng_ust_fixup_tls();
@@ -1350,7 +1396,12 @@ restart:
                prev_connect_failed = 0;
        }
 
+       if (ust_lock()) {
+               goto quit;
+       }
+
        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",
@@ -1359,6 +1410,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",
@@ -1367,6 +1419,7 @@ restart:
                sock_info->notify_socket = -1;
        }
 
+
        /*
         * Register. We need to perform both connect and sending
         * registration message before doing the next connect otherwise
@@ -1375,16 +1428,14 @@ restart:
         * first connect registration message.
         */
        /* Connect cmd socket */
+       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.
@@ -1394,8 +1445,28 @@ restart:
                ust_unlock();
                goto restart;
        }
+       fd = ret;
+       ret = lttng_ust_add_fd_to_tracker(fd);
+       if (ret < 0) {
+               ret = close(fd);
+               if (ret) {
+                       PERROR("close on sock_info->socket");
+               }
+               ret = -1;
+               lttng_ust_unlock_fd_tracker();
+               ust_unlock();
+               goto quit;
+       }
+
        sock_info->socket = ret;
+       lttng_ust_unlock_fd_tracker();
 
+       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;
        }
@@ -1430,18 +1501,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 */
+       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.
@@ -1451,7 +1528,32 @@ restart:
                ust_unlock();
                goto restart;
        }
+
+       fd = ret;
+       ret = lttng_ust_add_fd_to_tracker(fd);
+       if (ret < 0) {
+               ret = close(fd);
+               if (ret) {
+                       PERROR("close on sock_info->notify_socket");
+               }
+               ret = -1;
+               lttng_ust_unlock_fd_tracker();
+               ust_unlock();
+               goto quit;
+       }
+
        sock_info->notify_socket = ret;
+       lttng_ust_unlock_fd_tracker();
+
+       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) {
@@ -1475,10 +1577,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) {
@@ -1607,7 +1705,9 @@ void __attribute__((constructor)) lttng_ust_init(void)
         * sessiond before the init functions are completed).
         */
        init_usterr();
+       lttng_ust_getenv_init();        /* Needs init_usterr() to be completed. */
        init_tracepoint();
+       lttng_ust_init_fd_tracker();
        lttng_ust_clock_init();
        lttng_ust_getcpu_init();
        lttng_ust_statedump_init();
@@ -1624,6 +1724,8 @@ void __attribute__((constructor)) lttng_ust_init(void)
 
        timeout_mode = get_constructor_timeout(&constructor_timeout);
 
+       get_allow_blocking();
+
        ret = sem_init(&constructor_wait, 0, 0);
        if (ret) {
                PERROR("sem_init");
This page took 0.027661 seconds and 4 git commands to generate.