X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Fgetenv.c;h=120225e6bc888104262856849ea9a51fcb71151d;hb=HEAD;hp=1909f4cf912bd8f80ebf51e6fc5dd88bb866607c;hpb=910dcd720731c190adbfb9bb50c67bb9c4235003;p=lttng-ust.git diff --git a/src/common/getenv.c b/src/common/getenv.c index 1909f4cf..120225e6 100644 --- a/src/common/getenv.c +++ b/src/common/getenv.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "common/logging.h" #include "common/macros.h" @@ -25,20 +26,23 @@ struct lttng_env { char *value; }; -static -int lttng_ust_getenv_is_init = 0; +/* lttng_ust_getenv_init_mutex provides mutual exclusion for initialization. */ +static pthread_mutex_t lttng_ust_getenv_init_mutex = PTHREAD_MUTEX_INITIALIZER; +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, }, { "LTTNG_UST_REGISTER_TIMEOUT", LTTNG_ENV_NOT_SECURE, NULL, }, + { "LTTNG_UST_MAP_POPULATE_POLICY", LTTNG_ENV_NOT_SECURE, NULL, }, /* Env. var. which are not fetched in setuid/setgid executables. */ { "LTTNG_UST_CLOCK_PLUGIN", LTTNG_ENV_SECURE, NULL, }, @@ -46,6 +50,7 @@ static struct lttng_env lttng_env[] = { { "LTTNG_UST_ALLOW_BLOCKING", LTTNG_ENV_SECURE, NULL, }, { "HOME", LTTNG_ENV_SECURE, NULL, }, { "LTTNG_HOME", LTTNG_ENV_SECURE, NULL, }, + { "LTTNG_UST_APP_PATH", LTTNG_ENV_SECURE, NULL, }, }; static @@ -64,8 +69,11 @@ char *lttng_ust_getenv(const char *name) struct lttng_env *e; bool found = false; - if (!CMM_LOAD_SHARED(lttng_ust_getenv_is_init)) - abort(); + /* + * Perform lazy initialization of lttng_ust_getenv for early use + * by library constructors. + */ + lttng_ust_getenv_init(); for (i = 0; i < LTTNG_ARRAY_SIZE(lttng_env); i++) { e = <tng_env[i]; @@ -85,8 +93,25 @@ void lttng_ust_getenv_init(void) { size_t i; - if (CMM_LOAD_SHARED(lttng_ust_getenv_is_init)) + /* + * Return early if the init has already completed. + */ + if (CMM_LOAD_SHARED(lttng_ust_getenv_is_init)) { + /* + * Load lttng_ust_getenv_is_init before reading environment cache. + */ + cmm_smp_rmb(); return; + } + + pthread_mutex_lock(<tng_ust_getenv_init_mutex); + + /* + * Check again if the init has completed in another thread now that we + * have acquired the mutex. + */ + if (lttng_ust_getenv_is_init) + goto end_init; for (i = 0; i < LTTNG_ARRAY_SIZE(lttng_env); i++) { struct lttng_env *e = <tng_env[i]; @@ -98,5 +123,12 @@ void lttng_ust_getenv_init(void) } e->value = getenv(e->key); } + + /* + * Store environment cache before setting lttng_ust_getenv_is_init to 1. + */ + cmm_smp_wmb(); CMM_STORE_SHARED(lttng_ust_getenv_is_init, 1); +end_init: + pthread_mutex_unlock(<tng_ust_getenv_init_mutex); }