X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Fgetenv.c;h=120225e6bc888104262856849ea9a51fcb71151d;hb=HEAD;hp=23029508b161d126590d8ed3bbcc943e0e23aa8c;hpb=407937dc27362ba6f169a7b2a01e41f4ab6ede82;p=lttng-ust.git diff --git a/src/common/getenv.c b/src/common/getenv.c index 23029508..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 @@ -88,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]; @@ -101,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); }