From: Jérémie Galarneau Date: Wed, 6 Jul 2016 04:14:26 +0000 (-0400) Subject: Fix: handle negative (unlimited) system stack size limits X-Git-Tag: v2.9.0-rc1~98 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=4d5fb75f02db3ea42a5d9718f2c34dda4c485f76 Fix: handle negative (unlimited) system stack size limits This also changes the stack size selection policy to select the largest of: 1) default pthread stack size (dictated by libc) 2) system soft limit 3) 2 MB This is bounded by the system's hard limit on stack size. If this limit is smaller than 2 MB, the default size mentionned in pthread_create(3) for Linux, we warn the user that the daemons may be unreliable and advise bumping this limit. Note that is is most likely possible to operate the daemons with way less than 2MB of stack space. However, this was not extensively tested. Signed-off-by: Jérémie Galarneau --- diff --git a/src/common/defaults.c b/src/common/defaults.c index 00a026541..0303c887a 100644 --- a/src/common/defaults.c +++ b/src/common/defaults.c @@ -27,9 +27,8 @@ #include "align.h" #include "error.h" -static bool pthread_attr_init_done; +static int pthread_attr_init_done; static pthread_attr_t tattr; -static pthread_mutex_t tattr_lock = PTHREAD_MUTEX_INITIALIZER; LTTNG_HIDDEN size_t default_get_channel_subbuf_size(void) @@ -64,55 +63,93 @@ size_t default_get_ust_uid_channel_subbuf_size(void) LTTNG_HIDDEN pthread_attr_t *default_pthread_attr(void) { - int ret = 0; - size_t ptstacksize; - struct rlimit rlim; + if (pthread_attr_init_done) { + return &tattr; + } - pthread_mutex_lock(&tattr_lock); + WARN("Uninitializez pthread attributes, using libc defaults."); + return NULL; +} - /* Return cached value. */ - if (pthread_attr_init_done) { - goto end; +static void __attribute__((constructor)) init_default_pthread_attr(void) +{ + int ret; + struct rlimit rlim; + size_t pthread_ss, system_ss, selected_ss; + + ret = pthread_attr_init(&tattr); + if (ret) { + errno = ret; + PERROR("pthread_attr_init"); + goto error; } /* Get system stack size limits. */ ret = getrlimit(RLIMIT_STACK, &rlim); if (ret < 0) { PERROR("getrlimit"); - goto error; + goto error_destroy; } DBG("Stack size limits: soft %lld, hard %lld bytes", (long long) rlim.rlim_cur, (long long) rlim.rlim_max); + /* + * getrlimit() may return a stack size of "-1", meaning "unlimited". + * In this case, we impose a known-good default minimum value which will + * override the libc's default stack size if it is smaller. + */ + system_ss = rlim.rlim_cur != -1 ? rlim.rlim_cur : + DEFAULT_LTTNG_THREAD_STACK_SIZE; + /* Get pthread default thread stack size. */ - ret = pthread_attr_getstacksize(&tattr, &ptstacksize); + ret = pthread_attr_getstacksize(&tattr, &pthread_ss); if (ret < 0) { PERROR("pthread_attr_getstacksize"); - goto error; + goto error_destroy; } - DBG("Default pthread stack size is %zu bytes", ptstacksize); - - /* Check if the default pthread stack size honors ulimits. */ - if (ptstacksize < rlim.rlim_cur) { - DBG("Your libc doesn't honor stack size limits, setting thread stack size to soft limit (%lld bytes)", - (long long) rlim.rlim_cur); - - /* Create pthread_attr_t struct with ulimit stack size. */ - ret = pthread_attr_setstacksize(&tattr, rlim.rlim_cur); - if (ret < 0) { - PERROR("pthread_attr_setstacksize"); - goto error; - } + DBG("Default pthread stack size is %zu bytes", pthread_ss); + + selected_ss = max_t(size_t, pthread_ss, system_ss); + if (selected_ss < DEFAULT_LTTNG_THREAD_STACK_SIZE) { + DBG("Default stack size is too small, setting it to %zu bytes", + (size_t) DEFAULT_LTTNG_THREAD_STACK_SIZE); + selected_ss = DEFAULT_LTTNG_THREAD_STACK_SIZE; } - /* Enable cached value. */ - pthread_attr_init_done = true; -end: - pthread_mutex_unlock(&tattr_lock); - return &tattr; + if (rlim.rlim_max >= 0 && selected_ss > rlim.rlim_max) { + WARN("Your system's stack size restrictions (%zu bytes) may be too low for the LTTng daemons to function properly, please set the stack size limit to at leat %zu bytes to ensure reliable operation", + (size_t) rlim.rlim_max, (size_t) DEFAULT_LTTNG_THREAD_STACK_SIZE); + selected_ss = (size_t) rlim.rlim_max; + } + + ret = pthread_attr_setstacksize(&tattr, selected_ss); + if (ret < 0) { + PERROR("pthread_attr_setstacksize"); + goto error_destroy; + } + pthread_attr_init_done = 1; error: - pthread_mutex_unlock(&tattr_lock); - WARN("Failed to initialize pthread attributes, using libc defaults."); - return NULL; + return; +error_destroy: + ret = pthread_attr_destroy(&tattr); + if (ret) { + errno = ret; + PERROR("pthread_attr_destroy"); + } +} + +static void __attribute__((destructor)) fini_default_pthread_attr(void) +{ + int ret; + + if (!pthread_attr_init_done) { + return; + } + + ret = pthread_attr_destroy(&tattr); + if (ret) { + errno = ret; + PERROR("pthread_attr_destroy"); + } } diff --git a/src/common/defaults.h b/src/common/defaults.h index 178a601df..27f1ddc82 100644 --- a/src/common/defaults.h +++ b/src/common/defaults.h @@ -309,6 +309,9 @@ /* Default LTTng MI XML namespace. */ #define DEFAULT_LTTNG_MI_NAMESPACE "http://lttng.org/xml/ns/lttng-mi" +/* Default thread stack size; the default mandated by pthread_create(3) */ +#define DEFAULT_LTTNG_THREAD_STACK_SIZE 2097152 + /* * Returns the default subbuf size. *