Fix: sessiond wait futex: handle spurious futex wakeups
[lttng-ust.git] / src / lib / lttng-ust / lttng-ust-comm.c
index 2f6fe18faefa2a604e594ef0e487a7dee5bdc376..7f34efe7a2f95ec9e934c0005d163bd71cd0ffcd 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SPDX-License-Identifier: LGPL-2.1-only
  *
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 EfficiOS Inc.
  * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  */
 
@@ -25,7 +25,6 @@
 #include <signal.h>
 #include <limits.h>
 #include <urcu/uatomic.h>
-#include "futex.h"
 #include <urcu/compiler.h>
 #include <lttng/urcu/urcu-ust.h>
 
 #include <lttng/ust-libc-wrapper.h>
 #include <lttng/ust-thread.h>
 #include <lttng/ust-tracer.h>
+#include <lttng/ust-common.h>
+#include <lttng/ust-cancelstate.h>
 #include <urcu/tls-compat.h>
+#include "lib/lttng-ust/futex.h"
 #include "common/ustcomm.h"
 #include "common/ust-fd.h"
 #include "common/logging.h"
 #include "common/macros.h"
-#include "tracepoint-internal.h"
+#include "common/tracepoint.h"
 #include "lttng-tracer-core.h"
 #include "common/compat/pthread.h"
 #include "common/procname.h"
 #include "common/ringbuffer/rb-init.h"
 #include "lttng-ust-statedump.h"
-#include "clock.h"
-#include "lib/lttng-ust/getcpu.h"
+#include "common/clock.h"
 #include "common/getenv.h"
-#include "ust-events-internal.h"
+#include "lib/lttng-ust/events.h"
 #include "context-internal.h"
 #include "common/align.h"
-#include "lttng-counter-client.h"
-#include "lttng-rb-clients.h"
+#include "common/counter-clients/clients.h"
+#include "common/ringbuffer-clients/clients.h"
 
 /*
  * Has lttng ust comm constructor been called ?
@@ -117,6 +118,28 @@ static int lttng_ust_comm_should_quit;
  */
 int lttng_ust_loaded __attribute__((weak));
 
+/*
+ * Notes on async-signal-safety of ust lock: a few libc functions are used
+ * which are not strictly async-signal-safe:
+ *
+ * - pthread_setcancelstate
+ * - pthread_mutex_lock
+ * - pthread_mutex_unlock
+ *
+ * As of glibc 2.35, the implementation of pthread_setcancelstate only
+ * touches TLS data, and it appears to be safe to use from signal
+ * handlers. If the libc implementation changes, this will need to be
+ * revisited, and we may ask glibc to provide an async-signal-safe
+ * pthread_setcancelstate.
+ *
+ * As of glibc 2.35, the implementation of pthread_mutex_lock/unlock
+ * for fast mutexes only relies on the pthread_mutex_t structure.
+ * Disabling signals around all uses of this mutex ensures
+ * signal-safety. If the libc implementation changes and eventually uses
+ * other global resources, this will need to be revisited and we may
+ * need to implement our own mutex.
+ */
+
 /*
  * Return 0 on success, -1 if should quit.
  * The lock is taken in both cases.
@@ -125,25 +148,21 @@ int lttng_ust_loaded __attribute__((weak));
 int ust_lock(void)
 {
        sigset_t sig_all_blocked, orig_mask;
-       int ret, oldstate;
+       int ret;
 
-       ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
-       if (ret) {
-               ERR("pthread_setcancelstate: %s", strerror(ret));
-       }
-       if (oldstate != PTHREAD_CANCEL_ENABLE) {
-               ERR("pthread_setcancelstate: unexpected oldstate");
+       if (lttng_ust_cancelstate_disable_push()) {
+               ERR("lttng_ust_cancelstate_disable_push");
        }
        sigfillset(&sig_all_blocked);
        ret = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_mask);
        if (ret) {
-               ERR("pthread_sigmask: %s", strerror(ret));
+               ERR("pthread_sigmask: ret=%d", ret);
        }
        if (!URCU_TLS(ust_mutex_nest)++)
                pthread_mutex_lock(&ust_mutex);
        ret = pthread_sigmask(SIG_SETMASK, &orig_mask, NULL);
        if (ret) {
-               ERR("pthread_sigmask: %s", strerror(ret));
+               ERR("pthread_sigmask: ret=%d", ret);
        }
        if (lttng_ust_comm_should_quit) {
                return -1;
@@ -161,25 +180,21 @@ int ust_lock(void)
 void ust_lock_nocheck(void)
 {
        sigset_t sig_all_blocked, orig_mask;
-       int ret, oldstate;
+       int ret;
 
-       ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
-       if (ret) {
-               ERR("pthread_setcancelstate: %s", strerror(ret));
-       }
-       if (oldstate != PTHREAD_CANCEL_ENABLE) {
-               ERR("pthread_setcancelstate: unexpected oldstate");
+       if (lttng_ust_cancelstate_disable_push()) {
+               ERR("lttng_ust_cancelstate_disable_push");
        }
        sigfillset(&sig_all_blocked);
        ret = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_mask);
        if (ret) {
-               ERR("pthread_sigmask: %s", strerror(ret));
+               ERR("pthread_sigmask: ret=%d", ret);
        }
        if (!URCU_TLS(ust_mutex_nest)++)
                pthread_mutex_lock(&ust_mutex);
        ret = pthread_sigmask(SIG_SETMASK, &orig_mask, NULL);
        if (ret) {
-               ERR("pthread_sigmask: %s", strerror(ret));
+               ERR("pthread_sigmask: ret=%d", ret);
        }
 }
 
@@ -189,25 +204,21 @@ void ust_lock_nocheck(void)
 void ust_unlock(void)
 {
        sigset_t sig_all_blocked, orig_mask;
-       int ret, oldstate;
+       int ret;
 
        sigfillset(&sig_all_blocked);
        ret = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_mask);
        if (ret) {
-               ERR("pthread_sigmask: %s", strerror(ret));
+               ERR("pthread_sigmask: ret=%d", ret);
        }
        if (!--URCU_TLS(ust_mutex_nest))
                pthread_mutex_unlock(&ust_mutex);
        ret = pthread_sigmask(SIG_SETMASK, &orig_mask, NULL);
        if (ret) {
-               ERR("pthread_sigmask: %s", strerror(ret));
-       }
-       ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
-       if (ret) {
-               ERR("pthread_setcancelstate: %s", strerror(ret));
+               ERR("pthread_sigmask: ret=%d", ret);
        }
-       if (oldstate != PTHREAD_CANCEL_DISABLE) {
-               ERR("pthread_setcancelstate: unexpected oldstate");
+       if (lttng_ust_cancelstate_disable_pop()) {
+               ERR("lttng_ust_cancelstate_disable_pop");
        }
 }
 
@@ -259,11 +270,11 @@ struct sock_info {
        int statedump_pending;
        int initial_statedump_done;
        /* Keep procname for statedump */
-       char procname[LTTNG_UST_ABI_PROCNAME_LEN];
+       char procname[LTTNG_UST_CONTEXT_PROCNAME_LEN];
 };
 
 /* Socket from app (connect) to session daemon (listen) for communication */
-struct sock_info global_apps = {
+static struct sock_info global_apps = {
        .name = "global",
        .global = 1,
 
@@ -285,7 +296,7 @@ struct sock_info global_apps = {
 
 /* TODO: allow global_apps_sock_path override */
 
-struct sock_info local_apps = {
+static struct sock_info local_apps = {
        .name = "local",
        .global = 0,
        .root_handle = -1,
@@ -356,24 +367,6 @@ static int got_timeout_env;
 
 static char *get_map_shm(struct sock_info *sock_info);
 
-ssize_t lttng_ust_read(int fd, void *buf, size_t len)
-{
-       ssize_t ret;
-       size_t copied = 0, to_copy = len;
-
-       do {
-               ret = read(fd, buf + copied, to_copy);
-               if (ret > 0) {
-                       copied += ret;
-                       to_copy -= ret;
-               }
-       } while ((ret > 0 && to_copy > 0)
-               || (ret < 0 && errno == EINTR));
-       if (ret > 0) {
-               ret = copied;
-       }
-       return ret;
-}
 /*
  * Returns the HOME directory path. Caller MUST NOT free(3) the returned
  * pointer.
@@ -391,48 +384,48 @@ const char *get_lttng_home_dir(void)
 }
 
 /*
- * Force a read (imply TLS fixup for dlopen) of TLS variables.
+ * Force a read (imply TLS allocation for dlopen) of TLS variables.
  */
 static
-void lttng_fixup_nest_count_tls(void)
+void lttng_nest_count_alloc_tls(void)
 {
        asm volatile ("" : : "m" (URCU_TLS(lttng_ust_nest_count)));
 }
 
 static
-void lttng_fixup_ust_mutex_nest_tls(void)
+void lttng_ust_mutex_nest_alloc_tls(void)
 {
        asm volatile ("" : : "m" (URCU_TLS(ust_mutex_nest)));
 }
 
 /*
- * Fixup lttng-ust urcu TLS.
+ * Allocate lttng-ust urcu TLS.
  */
 static
-void lttng_fixup_lttng_ust_urcu_tls(void)
+void lttng_lttng_ust_urcu_alloc_tls(void)
 {
        (void) lttng_ust_urcu_read_ongoing();
 }
 
-void lttng_ust_fixup_tls(void)
+void lttng_ust_alloc_tls(void)
 {
-       lttng_fixup_lttng_ust_urcu_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_perf_counter_tls();
-       lttng_ust_fixup_fd_tracker_tls();
-       lttng_fixup_cgroup_ns_tls();
-       lttng_fixup_ipc_ns_tls();
-       lttng_fixup_net_ns_tls();
-       lttng_fixup_time_ns_tls();
-       lttng_fixup_uts_ns_tls();
-       lttng_ust_fixup_ring_buffer_client_discard_tls();
-       lttng_ust_fixup_ring_buffer_client_discard_rt_tls();
-       lttng_ust_fixup_ring_buffer_client_overwrite_tls();
-       lttng_ust_fixup_ring_buffer_client_overwrite_rt_tls();
+       lttng_lttng_ust_urcu_alloc_tls();
+       lttng_ringbuffer_alloc_tls();
+       lttng_vtid_alloc_tls();
+       lttng_nest_count_alloc_tls();
+       lttng_procname_alloc_tls();
+       lttng_ust_mutex_nest_alloc_tls();
+       lttng_ust_perf_counter_alloc_tls();
+       lttng_ust_common_alloc_tls();
+       lttng_cgroup_ns_alloc_tls();
+       lttng_ipc_ns_alloc_tls();
+       lttng_net_ns_alloc_tls();
+       lttng_time_ns_alloc_tls();
+       lttng_uts_ns_alloc_tls();
+       lttng_ust_ring_buffer_client_discard_alloc_tls();
+       lttng_ust_ring_buffer_client_discard_rt_alloc_tls();
+       lttng_ust_ring_buffer_client_overwrite_alloc_tls();
+       lttng_ust_ring_buffer_client_overwrite_rt_alloc_tls();
 }
 
 /*
@@ -453,7 +446,7 @@ void lttng_ust_init_thread(void)
         * ensure those are initialized before a signal handler nesting over
         * this thread attempts to use them.
         */
-       lttng_ust_fixup_tls();
+       lttng_ust_alloc_tls();
 }
 
 int lttng_get_notify_socket(void *owner)
@@ -500,7 +493,7 @@ int setup_global_apps(void)
        }
 
        global_apps.allowed = 1;
-       lttng_pthread_getname_np(global_apps.procname, LTTNG_UST_ABI_PROCNAME_LEN);
+       lttng_pthread_getname_np(global_apps.procname, LTTNG_UST_CONTEXT_PROCNAME_LEN);
 error:
        return ret;
 }
@@ -546,7 +539,7 @@ int setup_local_apps(void)
                goto end;
        }
 
-       lttng_pthread_getname_np(local_apps.procname, LTTNG_UST_ABI_PROCNAME_LEN);
+       lttng_pthread_getname_np(local_apps.procname, LTTNG_UST_CONTEXT_PROCNAME_LEN);
 end:
        return ret;
 }
@@ -638,7 +631,8 @@ void get_allow_blocking(void)
 }
 
 static
-int register_to_sessiond(int socket, enum ustctl_socket_type type)
+int register_to_sessiond(int socket, enum lttng_ust_ctl_socket_type type,
+               const char *procname)
 {
        return ustcomm_send_reg_msg(socket,
                type,
@@ -647,7 +641,8 @@ int register_to_sessiond(int socket, enum ustctl_socket_type type)
                lttng_ust_rb_alignof(uint16_t) * CHAR_BIT,
                lttng_ust_rb_alignof(uint32_t) * CHAR_BIT,
                lttng_ust_rb_alignof(uint64_t) * CHAR_BIT,
-               lttng_ust_rb_alignof(unsigned long) * CHAR_BIT);
+               lttng_ust_rb_alignof(unsigned long) * CHAR_BIT,
+               procname);
 }
 
 static
@@ -872,6 +867,49 @@ end:
        return ret;
 }
 
+static
+void prepare_cmd_reply(struct ustcomm_ust_reply *lur, uint32_t handle, uint32_t cmd, int ret)
+{
+       lur->handle = handle;
+       lur->cmd = cmd;
+       lur->ret_val = ret;
+       if (ret >= 0) {
+               lur->ret_code = LTTNG_UST_OK;
+       } else {
+               /*
+                * Use -LTTNG_UST_ERR as wildcard for UST internal
+                * error that are not caused by the transport, except if
+                * we already have a more precise error message to
+                * report.
+                */
+               if (ret > -LTTNG_UST_ERR) {
+                       /* Translate code to UST error. */
+                       switch (ret) {
+                       case -EEXIST:
+                               lur->ret_code = -LTTNG_UST_ERR_EXIST;
+                               break;
+                       case -EINVAL:
+                               lur->ret_code = -LTTNG_UST_ERR_INVAL;
+                               break;
+                       case -ENOENT:
+                               lur->ret_code = -LTTNG_UST_ERR_NOENT;
+                               break;
+                       case -EPERM:
+                               lur->ret_code = -LTTNG_UST_ERR_PERM;
+                               break;
+                       case -ENOSYS:
+                               lur->ret_code = -LTTNG_UST_ERR_NOSYS;
+                               break;
+                       default:
+                               lur->ret_code = -LTTNG_UST_ERR;
+                               break;
+                       }
+               } else {
+                       lur->ret_code = ret;
+               }
+       }
+}
+
 static
 int handle_message(struct sock_info *sock_info,
                int sock, struct ustcomm_ust_msg *lum)
@@ -896,6 +934,52 @@ int handle_message(struct sock_info *sock_info,
                goto error;
        }
 
+       switch (lum->cmd) {
+       case LTTNG_UST_ABI_FILTER:
+       case LTTNG_UST_ABI_EXCLUSION:
+       case LTTNG_UST_ABI_CHANNEL:
+       case LTTNG_UST_ABI_STREAM:
+       case LTTNG_UST_ABI_CONTEXT:
+               /*
+                * Those commands send additional payload after struct
+                * ustcomm_ust_msg, which makes it pretty much impossible to
+                * deal with "unknown command" errors without leaving the
+                * communication pipe in a out-of-sync state. This is part of
+                * the ABI between liblttng-ust-ctl and liblttng-ust, and
+                * should be fixed on the next breaking
+                * LTTNG_UST_ABI_MAJOR_VERSION protocol bump by indicating the
+                * total command message length as part of a message header so
+                * that the protocol can recover from invalid command errors.
+                */
+               break;
+
+       case LTTNG_UST_ABI_CAPTURE:
+       case LTTNG_UST_ABI_COUNTER:
+       case LTTNG_UST_ABI_COUNTER_GLOBAL:
+       case LTTNG_UST_ABI_COUNTER_CPU:
+       case LTTNG_UST_ABI_EVENT_NOTIFIER_CREATE:
+       case LTTNG_UST_ABI_EVENT_NOTIFIER_GROUP_CREATE:
+               /*
+                * Those commands expect a reply to the struct ustcomm_ust_msg
+                * before sending additional payload.
+                */
+               prepare_cmd_reply(&lur, lum->handle, lum->cmd, 0);
+
+               ret = send_reply(sock, &lur);
+               if (ret < 0) {
+                       DBG("error sending reply");
+                       goto error;
+               }
+               break;
+
+       default:
+               /*
+                * Other commands either don't send additional payload, or are
+                * unknown.
+                */
+               break;
+       }
+
        switch (lum->cmd) {
        case LTTNG_UST_ABI_REGISTER_DONE:
                if (lum->handle == LTTNG_UST_ABI_ROOT_HANDLE)
@@ -1313,44 +1397,8 @@ int handle_message(struct sock_info *sock_info,
                break;
        }
 
-       lur.handle = lum->handle;
-       lur.cmd = lum->cmd;
-       lur.ret_val = ret;
-       if (ret >= 0) {
-               lur.ret_code = LTTNG_UST_OK;
-       } else {
-               /*
-                * Use -LTTNG_UST_ERR as wildcard for UST internal
-                * error that are not caused by the transport, except if
-                * we already have a more precise error message to
-                * report.
-                */
-               if (ret > -LTTNG_UST_ERR) {
-                       /* Translate code to UST error. */
-                       switch (ret) {
-                       case -EEXIST:
-                               lur.ret_code = -LTTNG_UST_ERR_EXIST;
-                               break;
-                       case -EINVAL:
-                               lur.ret_code = -LTTNG_UST_ERR_INVAL;
-                               break;
-                       case -ENOENT:
-                               lur.ret_code = -LTTNG_UST_ERR_NOENT;
-                               break;
-                       case -EPERM:
-                               lur.ret_code = -LTTNG_UST_ERR_PERM;
-                               break;
-                       case -ENOSYS:
-                               lur.ret_code = -LTTNG_UST_ERR_NOSYS;
-                               break;
-                       default:
-                               lur.ret_code = -LTTNG_UST_ERR;
-                               break;
-                       }
-               } else {
-                       lur.ret_code = ret;
-               }
-       }
+       prepare_cmd_reply(&lur, lum->handle, lum->cmd, ret);
+
        if (ret >= 0) {
                switch (lum->cmd) {
                case LTTNG_UST_ABI_TRACER_VERSION:
@@ -1422,8 +1470,7 @@ void cleanup_sock_info(struct sock_info *sock_info, int exiting)
                }
                sock_info->root_handle = -1;
        }
-       sock_info->registration_done = 0;
-       sock_info->initial_statedump_done = 0;
+
 
        /*
         * wait_shm_mmap, socket and notify socket are used by listener
@@ -1435,6 +1482,9 @@ void cleanup_sock_info(struct sock_info *sock_info, int exiting)
        if (exiting)
                return;
 
+       sock_info->registration_done = 0;
+       sock_info->initial_statedump_done = 0;
+
        if (sock_info->socket != -1) {
                ret = ustcomm_close_unix_sock(sock_info->socket);
                if (ret) {
@@ -1707,18 +1757,25 @@ void wait_for_sessiond(struct sock_info *sock_info)
 
        DBG("Waiting for %s apps sessiond", sock_info->name);
        /* Wait for futex wakeup */
-       if (uatomic_read((int32_t *) sock_info->wait_shm_mmap))
-               goto end_wait;
-
-       while (lttng_ust_futex_async((int32_t *) sock_info->wait_shm_mmap,
-                       FUTEX_WAIT, 0, NULL, NULL, 0)) {
+       while (!uatomic_read((int32_t *) sock_info->wait_shm_mmap)) {
+               if (!lttng_ust_futex_async((int32_t *) sock_info->wait_shm_mmap, FUTEX_WAIT, 0, NULL, NULL, 0)) {
+                       /*
+                        * Prior queued wakeups queued by unrelated code
+                        * using the same address can cause futex wait to
+                        * return 0 even through the futex value is still
+                        * 0 (spurious wakeups). Check the value again
+                        * in user-space to validate whether it really
+                        * differs from 0.
+                        */
+                       continue;
+               }
                switch (errno) {
-               case EWOULDBLOCK:
+               case EAGAIN:
                        /* Value already changed. */
                        goto end_wait;
                case EINTR:
                        /* Retry if interrupted by signal. */
-                       break;  /* Get out of switch. */
+                       break;  /* Get out of switch. Check again. */
                case EFAULT:
                        wait_poll_fallback = 1;
                        DBG(
@@ -1758,7 +1815,7 @@ void *ust_listener_thread(void *arg)
        int sock, ret, prev_connect_failed = 0, has_waited = 0, fd;
        long timeout;
 
-       lttng_ust_fixup_tls();
+       lttng_ust_alloc_tls();
        /*
         * If available, add '-ust' to the end of this thread's
         * process name
@@ -1876,7 +1933,8 @@ restart:
                sock_info->root_handle = ret;
        }
 
-       ret = register_to_sessiond(sock_info->socket, USTCTL_SOCKET_CMD);
+       ret = register_to_sessiond(sock_info->socket, LTTNG_UST_CTL_SOCKET_CMD,
+               sock_info->procname);
        if (ret < 0) {
                ERR("Error registering to %s ust cmd socket",
                        sock_info->name);
@@ -1969,7 +2027,7 @@ restart:
        }
 
        ret = register_to_sessiond(sock_info->notify_socket,
-                       USTCTL_SOCKET_NOTIFY);
+                       LTTNG_UST_CTL_SOCKET_NOTIFY, sock_info->procname);
        if (ret < 0) {
                ERR("Error registering to %s ust notify socket",
                        sock_info->name);
@@ -2061,19 +2119,54 @@ quit:
  * Weak symbol to call when the ust malloc wrapper is not loaded.
  */
 __attribute__((weak))
-void lttng_ust_libc_wrapper_malloc_init(void)
+void lttng_ust_libc_wrapper_malloc_ctor(void)
 {
 }
 
+/*
+ * Use a symbol of the previous ABI to detect if liblttng-ust.so.0 is loaded in
+ * the current process.
+ */
+#define LTTNG_UST_SONAME_0_SYM "ltt_probe_register"
+
+static
+void lttng_ust_check_soname_0(void)
+{
+       if (!dlsym(RTLD_DEFAULT, LTTNG_UST_SONAME_0_SYM))
+               return;
+
+       CRIT("Incompatible library ABIs detected within the same process. "
+               "The process is likely linked against different major soname of LTTng-UST which is unsupported. "
+               "The detection was triggered by lookup of ABI 0 symbol \"%s\" in the Global Symbol Table\n",
+               LTTNG_UST_SONAME_0_SYM);
+}
+
+/*
+ * Expose a canary symbol of the previous ABI to ensure we catch uses of a
+ * liblttng-ust.so.0 dlopen'd after .so.1 has been loaded. Use a different
+ * symbol than the detection code to ensure we don't detect ourself.
+ *
+ * This scheme will only work on systems where the global symbol table has
+ * priority when resolving the symbols of a dlopened shared object, which is
+ * the case on Linux but not on FreeBSD.
+ */
+void init_usterr(void);
+void init_usterr(void)
+{
+       CRIT("Incompatible library ABIs detected within the same process. "
+               "The process is likely linked against different major soname of LTTng-UST which is unsupported. "
+               "The detection was triggered by canary symbol \"%s\"\n", __func__);
+}
+
 /*
  * sessiond monitoring thread: monitor presence of global and per-user
  * sessiond by polling the application common named pipe.
  */
 static
-void lttng_ust_init(void)
+void lttng_ust_ctor(void)
        __attribute__((constructor));
 static
-void lttng_ust_init(void)
+void lttng_ust_ctor(void)
 {
        struct timespec constructor_timeout;
        sigset_t sig_all_blocked, orig_parent_mask;
@@ -2086,14 +2179,22 @@ void lttng_ust_init(void)
                return;
 
        /*
-        * Fixup interdependency between TLS fixup mutex (which happens
+        * Fixup interdependency between TLS allocation mutex (which happens
         * to be the dynamic linker mutex) and ust_lock, taken within
         * the ust lock.
         */
-       lttng_ust_fixup_tls();
+       lttng_ust_alloc_tls();
 
        lttng_ust_loaded = 1;
 
+       /*
+        * Check if we find a symbol of the previous ABI in the current process
+        * as different ABIs of liblttng-ust can't co-exist in a process. If we
+        * do so, emit a critical log message which will also abort if the
+        * LTTNG_UST_ABORT_ON_CRITICAL environment variable is set.
+        */
+       lttng_ust_check_soname_0();
+
        /*
         * We need to ensure that the liblttng-ust library is not unloaded to avoid
         * the unloading of code used by the ust_listener_threads as we can not
@@ -2102,7 +2203,7 @@ void lttng_ust_init(void)
         * this library so it never becomes zero, thus never gets unloaded from the
         * address space of the process. Since we are already running in the
         * constructor of the LTTNG_UST_LIB_SONAME library, calling dlopen will
-        * simply increment the refcount and no additionnal work is needed by the
+        * simply increment the refcount and no additional work is needed by the
         * dynamic loader as the shared library is already loaded in the address
         * space. As a safe guard, we use the RTLD_NODELETE flag to prevent
         * unloading of the UST library if its refcount becomes zero (which should
@@ -2112,6 +2213,8 @@ void lttng_ust_init(void)
        handle = dlopen(LTTNG_UST_LIB_SONAME, RTLD_LAZY | RTLD_NODELETE);
        if (!handle) {
                ERR("dlopen of liblttng-ust shared library (%s).", LTTNG_UST_LIB_SONAME);
+       } else {
+               DBG("dlopened liblttng-ust shared library (%s).", LTTNG_UST_LIB_SONAME);
        }
 
        /*
@@ -2120,12 +2223,21 @@ void lttng_ust_init(void)
         * sessiond (otherwise leading to errors when trying to create
         * sessiond before the init functions are completed).
         */
+
+       /*
+        * Both the logging and getenv lazy-initialization uses getenv()
+        * internally and thus needs to be explicitly initialized in
+        * liblttng-ust before we start any threads as an unsuspecting normally
+        * single threaded application using liblttng-ust could be using
+        * setenv() which is not thread-safe.
+        */
        lttng_ust_logging_init();
-       lttng_ust_getenv_init();        /* Needs lttng_ust_logging_init() to be completed. */
+       lttng_ust_getenv_init();
+
+       /* Call the liblttng-ust-common constructor. */
+       lttng_ust_common_ctor();
+
        lttng_ust_tp_init();
-       lttng_ust_init_fd_tracker();
-       lttng_ust_clock_init();
-       lttng_ust_getcpu_plugin_init();
        lttng_ust_statedump_init();
        lttng_ust_ring_buffer_clients_init();
        lttng_ust_counter_clients_init();
@@ -2133,7 +2245,7 @@ void lttng_ust_init(void)
        /*
         * Invoke ust malloc wrapper init before starting other threads.
         */
-       lttng_ust_libc_wrapper_malloc_init();
+       lttng_ust_libc_wrapper_malloc_ctor();
 
        timeout_mode = get_constructor_timeout(&constructor_timeout);
 
@@ -2384,8 +2496,8 @@ void lttng_ust_before_fork(sigset_t *save_sigset)
        sigset_t all_sigs;
        int ret;
 
-       /* Fixup lttng-ust TLS. */
-       lttng_ust_fixup_tls();
+       /* Allocate lttng-ust TLS. */
+       lttng_ust_alloc_tls();
 
        if (URCU_TLS(lttng_ust_nest_count))
                return;
@@ -2428,7 +2540,7 @@ void lttng_ust_after_fork_parent(sigset_t *restore_sigset)
                return;
        DBG("process %d", getpid());
        lttng_ust_urcu_after_fork_parent();
-       /* Release mutexes and reenable signals */
+       /* Release mutexes and re-enable signals */
        ust_after_fork_common(restore_sigset);
 }
 
@@ -2436,7 +2548,7 @@ void lttng_ust_after_fork_parent(sigset_t *restore_sigset)
  * After fork, in the child, we need to cleanup all the leftover state,
  * except the worker thread which already magically disappeared thanks
  * to the weird Linux fork semantics. After tyding up, we call
- * lttng_ust_init() again to start over as a new PID.
+ * lttng_ust_ctor() again to start over as a new PID.
  *
  * This is meant for forks() that have tracing in the child between the
  * fork and following exec call (if there is any).
@@ -2455,9 +2567,9 @@ void lttng_ust_after_fork_child(sigset_t *restore_sigset)
        /* Release urcu mutexes */
        lttng_ust_urcu_after_fork_child();
        lttng_ust_cleanup(0);
-       /* Release mutexes and reenable signals */
+       /* Release mutexes and re-enable signals */
        ust_after_fork_common(restore_sigset);
-       lttng_ust_init();
+       lttng_ust_ctor();
 }
 
 void lttng_ust_after_setns(void)
This page took 0.033559 seconds and 4 git commands to generate.