Internal logging lazy-initialization
authorMichael Jeanson <mjeanson@efficios.com>
Wed, 14 Apr 2021 17:39:03 +0000 (13:39 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Mon, 19 Apr 2021 17:31:10 +0000 (13:31 -0400)
Replace the initialization function by a lazy-init scheme, this way we
don't loose logging messages when called from constructors across
libraries or ld preloaded wrappers.

Change-Id: Idb1593c025351af6aed152b31a2aab17b4d884b0
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
src/common/logging.c
src/common/logging.h
src/lib/lttng-ust-common/ust-common.c
src/lib/lttng-ust-ctl/ustctl.c
src/lib/lttng-ust-dl/lttng-ust-dl.c
src/lib/lttng-ust/lttng-ust-comm.c

index eb610833676d46519cd7e7437e36d00df3f84654..fb3f119fcbba3c34e32e6741c6686c17f33ed6a3 100644 (file)
@@ -4,24 +4,57 @@
  * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  */
 
+#include <urcu/compiler.h>
+#include <urcu/system.h>
+
 #include "common/logging.h"
 
-volatile enum lttng_ust_log_level lttng_ust_log_level;
+int lttng_ust_log_level = LTTNG_UST_LOG_LEVEL_UNKNOWN;
 
-void lttng_ust_logging_init(void)
+/*
+ * Initialize the global log level from the "LTTNG_UST_DEBUG" environment
+ * variable.
+ *
+ * This could end up being called concurently by multiple threads but doesn't
+ * require a mutex since the input is invariant across threads and the result
+ * will be the same.
+ *
+ * Return the current log level to save the caller a second read of the global
+ * log level.
+ */
+int lttng_ust_logging_init(void)
 {
        char *lttng_ust_debug;
+       int current_log_level;
+
+       current_log_level = CMM_LOAD_SHARED(lttng_ust_log_level);
+
+       /*
+        * Check early if we are initialized, this is unlikely as it's already tested
+        * in lttng_ust_debug_enabled before performing lazy initialization.
+        */
+       if (caa_unlikely(current_log_level != LTTNG_UST_LOG_LEVEL_UNKNOWN))
+               goto end;
+
+       /*
+        * This getenv is not part of lttng_ust_getenv() because logging is
+        * used in the getenv initialization and thus logging must be
+        * initialized prior to getenv.
+        */
+       lttng_ust_debug = getenv("LTTNG_UST_DEBUG");
+
+       /*
+        * If the LTTNG_UST_DEBUG environment variable is defined, print all
+        * messages, otherwise print nothing.
+        */
+       if (lttng_ust_debug)
+               current_log_level = LTTNG_UST_LOG_LEVEL_DEBUG;
+       else
+               current_log_level = LTTNG_UST_LOG_LEVEL_SILENT;
+
+       /* Initialize the log level */
+       CMM_STORE_SHARED(lttng_ust_log_level, current_log_level);
 
-       if (lttng_ust_log_level == LTTNG_UST_LOG_LEVEL_UNKNOWN) {
-               /*
-                * This getenv is not part of lttng_ust_getenv() because it
-                * is required to print ERR() performed during getenv
-                * initialization.
-                */
-               lttng_ust_debug = getenv("LTTNG_UST_DEBUG");
-               if (lttng_ust_debug)
-                       lttng_ust_log_level = LTTNG_UST_LOG_LEVEL_DEBUG;
-               else
-                       lttng_ust_log_level = LTTNG_UST_LOG_LEVEL_NORMAL;
-       }
+end:
+       return current_log_level;
 }
index ab125e7c3dfc139d987e8a2d4192e18fe5de05cd..5ebf17bf2900773f05b0e2e82d09bff9e3697969 100644 (file)
@@ -16,6 +16,8 @@
 #include <stdio.h>
 
 #include <lttng/ust-utils.h>
+#include <urcu/compiler.h>
+#include <urcu/system.h>
 
 #include "common/patient.h"
 #include "common/compat/tid.h"
 
 enum lttng_ust_log_level {
        LTTNG_UST_LOG_LEVEL_UNKNOWN = 0,
-       LTTNG_UST_LOG_LEVEL_NORMAL,
+       LTTNG_UST_LOG_LEVEL_SILENT,
        LTTNG_UST_LOG_LEVEL_DEBUG,
 };
 
-extern volatile enum lttng_ust_log_level lttng_ust_log_level
+extern int lttng_ust_log_level                 /* enum lttng_ust_log_level */
        __attribute__((visibility("hidden")));
 
-void lttng_ust_logging_init(void)
+/*
+ * Initialize the global log level from the "LTTNG_UST_DEBUG" environment
+ * variable.
+ *
+ * This could end up being called concurrently by multiple threads but doesn't
+ * require a mutex since the input is invariant across threads and the result
+ * will be the same.
+ *
+ * Return the current log level to save the caller a second read of the global
+ * log level.
+ */
+int lttng_ust_logging_init(void)
        __attribute__((visibility("hidden")));
 
 #ifdef LTTNG_UST_DEBUG
-static inline bool lttng_ust_logging_debug_enabled(void)
+static inline
+bool lttng_ust_logging_debug_enabled(void)
 {
        return true;
 }
 #else /* #ifdef LTTNG_UST_DEBUG */
-static inline bool lttng_ust_logging_debug_enabled(void)
+static inline
+bool lttng_ust_logging_debug_enabled(void)
 {
-       return lttng_ust_log_level == LTTNG_UST_LOG_LEVEL_DEBUG;
+       int current_log_level;
+
+       current_log_level = CMM_LOAD_SHARED(lttng_ust_log_level);
+
+       /* If the global log level is unknown, lazy-initialize it. */
+       if (caa_unlikely(current_log_level == LTTNG_UST_LOG_LEVEL_UNKNOWN))
+               current_log_level = lttng_ust_logging_init();
+
+       return current_log_level == LTTNG_UST_LOG_LEVEL_DEBUG;
 }
-#endif /* #else #ifdef LTTNG_UST_DEBUG */
+#endif /* #ifdef LTTNG_UST_DEBUG */
 
 /*
  * The default component for error messages.
index 036c1e288af9ee09ef6510bab12f6a86a145719f..cefff67a82d721d0c63c6940e86563ed9cf53c38 100644 (file)
@@ -13,9 +13,6 @@ void lttng_ust_common_init(void)
 static
 void lttng_ust_common_init(void)
 {
-       /* Initialize logging for liblttng-ust-common */
-       lttng_ust_logging_init();
-
        /*
         * Initialize the fd-tracker, other libraries using it should also call
         * this in their constructor in case it gets executed before this one.
index 817f89e426da57f5f91408b076b84eb543928c8a..394f197079b0d323a0cb312bde86f5ec4a88493d 100644 (file)
@@ -2906,8 +2906,6 @@ void ustctl_init(void)
 static
 void ustctl_init(void)
 {
-       lttng_ust_logging_init();
-       lttng_ust_getenv_init();        /* Needs lttng_ust_logging_init() to be completed. */
        lttng_ust_clock_init();
        lttng_ust_ring_buffer_clients_init();
        lttng_ust_counter_clients_init();
index 2b767e4760e95593518c0ba46a3de1e9aac7068e..e07136ce9d012d1c2d1d66641fc3d830349437c9 100644 (file)
@@ -36,15 +36,6 @@ static void *(*__lttng_ust_plibc_dlmopen)(Lmid_t nsid, const char *filename,
 #endif
 static int (*__lttng_ust_plibc_dlclose)(void *handle);
 
-static
-void _lttng_ust_dl_init(void)
-       __attribute__((constructor));
-static
-void _lttng_ust_dl_init(void)
-{
-       lttng_ust_logging_init();
-}
-
 static
 void *_lttng_ust_dl_libc_dlopen(const char *filename, int flags)
 {
index e02cffd28ed103da580191f769a97b52343a08f2..cd5b378c49be203d8d9fa72e37dc43f327fa86e3 100644 (file)
@@ -2120,8 +2120,17 @@ 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();
+
        lttng_ust_tp_init();
        lttng_ust_init_fd_tracker();
        lttng_ust_clock_init();
This page took 0.030854 seconds and 4 git commands to generate.