From 0afccdb0a48e776b93da4fb3962fa3a5c42f9bae Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 6 Sep 2017 17:41:13 +0200 Subject: [PATCH] linux: increase thread stack size with musl libc musl has tiny default thread stack sizes compared to glibc (80 kB vs. 2048 kB or more) so set an explicit stack size to harmonize between different libcs. Fixes: https://github.com/libuv/libuv/issues/1507 PR-URL: https://github.com/libuv/libuv/pull/1526 Reviewed-By: Colin Ihrig Reviewed-By: Santiago Gimeno --- src/unix/thread.c | 57 ++++++++++++++++++++++++++++++---------------- test/test-thread.c | 22 +++++++++++------- 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/unix/thread.c b/src/unix/thread.c index f8846225..35d3e77b 100644 --- a/src/unix/thread.c +++ b/src/unix/thread.c @@ -145,37 +145,56 @@ int pthread_barrier_destroy(pthread_barrier_t* barrier) { #endif -int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { - int err; - pthread_attr_t* attr; -#if defined(__APPLE__) - pthread_attr_t attr_storage; +/* On MacOS, threads other than the main thread are created with a reduced + * stack size by default. Adjust to RLIMIT_STACK aligned to the page size. + * + * On Linux, threads created by musl have a much smaller stack than threads + * created by glibc (80 vs. 2048 or 4096 kB.) Follow glibc for consistency. + */ +static size_t thread_stack_size(void) { +#if defined(__APPLE__) || defined(__linux__) struct rlimit lim; -#endif - /* On OSX threads other than the main thread are created with a reduced stack - * size by default, adjust it to RLIMIT_STACK. - */ -#if defined(__APPLE__) if (getrlimit(RLIMIT_STACK, &lim)) abort(); - attr = &attr_storage; - if (pthread_attr_init(attr)) - abort(); - if (lim.rlim_cur != RLIM_INFINITY) { /* pthread_attr_setstacksize() expects page-aligned values. */ lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize(); - if (lim.rlim_cur >= PTHREAD_STACK_MIN) - if (pthread_attr_setstacksize(attr, lim.rlim_cur)) - abort(); + return lim.rlim_cur; } -#else - attr = NULL; #endif +#if !defined(__linux__) + return 0; +#elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__) + return 4 << 20; /* glibc default. */ +#else + return 2 << 20; /* glibc default. */ +#endif +} + + +int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { + int err; + size_t stack_size; + pthread_attr_t* attr; + pthread_attr_t attr_storage; + + attr = NULL; + stack_size = thread_stack_size(); + + if (stack_size > 0) { + attr = &attr_storage; + + if (pthread_attr_init(attr)) + abort(); + + if (pthread_attr_setstacksize(attr, stack_size)) + abort(); + } + err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg); if (attr != NULL) diff --git a/test/test-thread.c b/test/test-thread.c index 10bec3fe..b0e87e20 100644 --- a/test/test-thread.c +++ b/test/test-thread.c @@ -211,22 +211,28 @@ TEST_IMPL(thread_local_storage) { } -#if defined(__APPLE__) static void thread_check_stack(void* arg) { - /* 512KB is the default stack size of threads other than the main thread - * on OSX. */ +#if defined(__APPLE__) + /* 512 kB is the default stack size of threads other than the main thread + * on MacOS. */ ASSERT(pthread_get_stacksize_np(pthread_self()) > 512*1024); -} +#elif defined(__linux__) && defined(__GLIBC__) + struct rlimit lim; + size_t stack_size; + pthread_attr_t attr; + ASSERT(0 == getrlimit(RLIMIT_STACK, &lim)); + if (lim.rlim_cur == RLIM_INFINITY) + lim.rlim_cur = 2 << 20; /* glibc default. */ + ASSERT(0 == pthread_getattr_np(pthread_self(), &attr)); + ASSERT(0 == pthread_attr_getstacksize(&attr, &stack_size)); + ASSERT(stack_size >= lim.rlim_cur); #endif +} TEST_IMPL(thread_stack_size) { -#if defined(__APPLE__) uv_thread_t thread; ASSERT(0 == uv_thread_create(&thread, thread_check_stack, NULL)); ASSERT(0 == uv_thread_join(&thread)); return 0; -#else - RETURN_SKIP("OSX only test"); -#endif }