Fix: handle negative (unlimited) system stack size limits
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 6 Jul 2016 04:14:26 +0000 (00:14 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 6 Jul 2016 04:15:04 +0000 (00:15 -0400)
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 <jeremie.galarneau@efficios.com>
src/common/defaults.c
src/common/defaults.h

index 00a0265414baaf693a0eb687e8ce05b9a8f23907..0303c887a885cecbaa43a10243c3af0227049a71 100644 (file)
@@ -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");
+       }
 }
index 178a601dfde3b38c619a421642564aefd078ac7a..27f1ddc82a66524afeef8250d50c2f0dfefa72c7 100644 (file)
 /* 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.
  *
This page took 0.02724 seconds and 4 git commands to generate.