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 <cjihrig@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
Ben Noordhuis 2017-09-06 17:41:13 +02:00
parent c0504885ea
commit 0afccdb0a4
2 changed files with 52 additions and 27 deletions

View File

@ -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)

View File

@ -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
}