Add critical log level
authorMichael Jeanson <mjeanson@efficios.com>
Thu, 13 May 2021 22:41:35 +0000 (18:41 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 14 May 2021 21:02:43 +0000 (17:02 -0400)
Rename the unused BUG() macro to CRIT() to signify an error that can't
be recovered from. Add a new environment variable
LTTNG_UST_ABORT_ON_CRITICAL that when set will abort() on a critical log
statement.

Change-Id: Ib3384a66b7efa4004677b3c153f86cb97b06a091
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
README.md
src/common/getenv.c
src/common/logging.c
src/common/logging.h

index 9553ef151940ad7e307cae587f459621b1fc0a17..e4fb9f2ddae6d3431cf935ee4965b0282242cb73 100644 (file)
--- a/README.md
+++ b/README.md
@@ -171,6 +171,10 @@ human-readable text log.
     variable `LTTNG_UST_DEBUG` when launching the user application. It
     can also be enabled at build time by compiling LTTng-UST with
     `-DLTTNG_UST_DEBUG`.
+  - `liblttng-ust` abort on critical can be activated by setting the
+    environment variable `LTTNG_UST_ABORT_ON_CRITICAL` when launching the user
+    application. It can also be enabled at build time by compiling LTTng-UST with
+    `-DLTTNG_UST_ABORT_ON_CRITICAL`.
   - The environment variable `LTTNG_UST_REGISTER_TIMEOUT` can be used to
     specify how long the applications should wait for the session
     daemon  _registration done_ command before proceeding to execute the
index bc7a4d4ac98ce2f7ccc434e94727d0778ce7338a..55e6ad7cc5a069130ffb2172890752ef3e0d22c6 100644 (file)
@@ -32,11 +32,12 @@ static int lttng_ust_getenv_is_init = 0;
 
 static struct lttng_env lttng_env[] = {
        /*
-        * LTTNG_UST_DEBUG is used directly by snprintf, because it
-        * needs to be already set for ERR() used in
-        * lttng_ust_getenv_init().
+        * LTTNG_UST_DEBUG and LTTNG_UST_ABORT_ON_CRITICAL are used directly by
+        * the internal logging, because they need to be already set for ERR()
+        * used in lttng_ust_getenv_init().
         */
        { "LTTNG_UST_DEBUG", LTTNG_ENV_NOT_SECURE, NULL, },
+       { "LTTNG_UST_ABORT_ON_CRITICAL", LTTNG_ENV_NOT_SECURE, NULL, },
 
        /* Env. var. which can be used in setuid/setgid executables. */
        { "LTTNG_UST_WITHOUT_BADDR_STATEDUMP", LTTNG_ENV_NOT_SECURE, NULL, },
index fb3f119fcbba3c34e32e6741c6686c17f33ed6a3..39b515ff9a9368f4c6b19cc4fd186b5b237954b7 100644 (file)
 #include "common/logging.h"
 
 int lttng_ust_log_level = LTTNG_UST_LOG_LEVEL_UNKNOWN;
+int lttng_ust_log_critical_action = LTTNG_UST_LOG_CRITICAL_ACTION_UNKNOWN;
 
 /*
  * 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
+ * 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)
+static
+void lttng_ust_logging_log_level_init(void)
 {
        char *lttng_ust_debug;
        int current_log_level;
@@ -31,10 +30,10 @@ int lttng_ust_logging_init(void)
 
        /*
         * Check early if we are initialized, this is unlikely as it's already tested
-        * in lttng_ust_debug_enabled before performing lazy initialization.
+        * in lttng_ust_logging_debug_enabled before performing lazy initialization.
         */
        if (caa_unlikely(current_log_level != LTTNG_UST_LOG_LEVEL_UNKNOWN))
-               goto end;
+               return;
 
        /*
         * This getenv is not part of lttng_ust_getenv() because logging is
@@ -54,7 +53,61 @@ int lttng_ust_logging_init(void)
 
        /* Initialize the log level */
        CMM_STORE_SHARED(lttng_ust_log_level, current_log_level);
+}
+
+/*
+ * Initialize the global log critical action from the "LTTNG_UST_ABORT_ON_CRITICAL"
+ * 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.
+ */
+static
+void lttng_ust_logging_log_critical_action_init(void)
+{
+       char *lttng_ust_abort_on_critical;
+       int current_log_critical_action;
 
-end:
-       return current_log_level;
+       current_log_critical_action = CMM_LOAD_SHARED(lttng_ust_log_critical_action);
+
+       /*
+        * Check early if we are initialized, this is unlikely as it's already tested
+        * in lttng_ust_logging_abort_on_critical_enabled before performing lazy initialization.
+        */
+       if (caa_unlikely(current_log_critical_action != LTTNG_UST_LOG_CRITICAL_ACTION_UNKNOWN))
+               return;
+
+       /*
+        * 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_abort_on_critical = getenv("LTTNG_UST_ABORT_ON_CRITICAL");
+
+       /*
+        * If the LTTNG_UST_ABORT_ON_CRITICAL environment variable is defined,
+        * call abort() on CRIT(), otherwise take no action.
+        */
+       if (lttng_ust_abort_on_critical)
+               current_log_critical_action = LTTNG_UST_LOG_CRITICAL_ACTION_ABORT;
+       else
+               current_log_critical_action = LTTNG_UST_LOG_CRITICAL_ACTION_NONE;
+
+       /* Initialize the log critical action */
+       CMM_STORE_SHARED(lttng_ust_log_critical_action, current_log_critical_action);
+}
+
+/*
+ * Initialize the global log level from the "LTTNG_UST_DEBUG" environment
+ * variable and the global log critical action from "LTTNG_UST_ABORT_ON_CRITICAL".
+ *
+ * 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.
+ */
+void lttng_ust_logging_init(void)
+{
+       lttng_ust_logging_log_level_init();
+       lttng_ust_logging_log_critical_action_init();
 }
index 5ebf17bf2900773f05b0e2e82d09bff9e3697969..c98644d87c8128c3caf2debe0e841f830c82ba22 100644 (file)
@@ -29,21 +29,27 @@ enum lttng_ust_log_level {
        LTTNG_UST_LOG_LEVEL_DEBUG,
 };
 
+enum lttng_ust_log_critical_action {
+       LTTNG_UST_LOG_CRITICAL_ACTION_UNKNOWN = 0,
+       LTTNG_UST_LOG_CRITICAL_ACTION_NONE,
+       LTTNG_UST_LOG_CRITICAL_ACTION_ABORT,
+};
+
 extern int lttng_ust_log_level                 /* enum lttng_ust_log_level */
        __attribute__((visibility("hidden")));
 
+extern int lttng_ust_log_critical_action               /* enum lttng_ust_log_critical_action */
+       __attribute__((visibility("hidden")));
+
 /*
  * Initialize the global log level from the "LTTNG_UST_DEBUG" environment
- * variable.
+ * variable and the global log critical action from "LTTNG_UST_ABORT_ON_CRITICAL".
  *
  * 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)
+void lttng_ust_logging_init(void)
        __attribute__((visibility("hidden")));
 
 #ifdef LTTNG_UST_DEBUG
@@ -61,15 +67,41 @@ bool lttng_ust_logging_debug_enabled(void)
        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();
+       if (caa_unlikely(current_log_level == LTTNG_UST_LOG_LEVEL_UNKNOWN)) {
+               lttng_ust_logging_init();
+               current_log_level = CMM_LOAD_SHARED(lttng_ust_log_level);
+       }
 
        return current_log_level == LTTNG_UST_LOG_LEVEL_DEBUG;
 }
 #endif /* #ifdef LTTNG_UST_DEBUG */
 
+#ifdef LTTNG_UST_ABORT_ON_CRITICAL
+static inline
+bool lttng_ust_logging_abort_on_critical_enabled(void)
+{
+       return true;
+}
+#else /* #ifdef LTTNG_UST_ABORT_ON_CRITICAL */
+static inline
+bool lttng_ust_logging_abort_on_critical_enabled(void)
+{
+       int current_log_critical_action;
+
+       current_log_critical_action = CMM_LOAD_SHARED(lttng_ust_log_critical_action);
+
+       /* If the global log critical action is unknown, lazy-initialize it. */
+       if (caa_unlikely(current_log_critical_action == LTTNG_UST_LOG_CRITICAL_ACTION_UNKNOWN)) {
+               lttng_ust_logging_init();
+               current_log_critical_action = CMM_LOAD_SHARED(lttng_ust_log_critical_action);
+       }
+
+       return current_log_critical_action == LTTNG_UST_LOG_CRITICAL_ACTION_ABORT;
+}
+#endif /* #ifdef LTTNG_UST_ABORT_ON_CRITICAL */
+
 /*
- * The default component for error messages.
+ * The default component for log statements.
  */
 #ifndef UST_COMPONENT
 #define UST_COMPONENT libust
@@ -113,7 +145,13 @@ do {                                                                       \
 #define DBG_raw(fmt, args...)  sigsafe_print_err(fmt, ## args)
 #define WARN(fmt, args...)     ERRMSG("Warning: " fmt, ## args)
 #define ERR(fmt, args...)      ERRMSG("Error: " fmt, ## args)
-#define BUG(fmt, args...)      ERRMSG("BUG: " fmt, ## args)
+#define CRIT(fmt, args...)                                             \
+       do {                                                            \
+               ERRMSG("Critical: " fmt, ## args);                      \
+               if (lttng_ust_logging_abort_on_critical_enabled()) {    \
+                       abort();                                        \
+               }                                                       \
+       } while(0)
 
 #if !defined(__GLIBC__) || ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !defined(_GNU_SOURCE))
 /*
This page took 0.028276 seconds and 4 git commands to generate.