From 36979639b74ceabb3a1005a75753bd7352fc2eb1 Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Tue, 25 Aug 2026 19:05:10 +0300 Subject: [PATCH] Reserve stack for wolfSSL's static TLS, and report a failed thread wolfSSL reserves about 48K of static thread-local storage. glibc counts that against the thread stack, so pthread_create() was refused with EINVAL and no service thread was ever created: the process started, listened on nothing, logged nothing and waited forever on the semaphore the thread was supposed to release. Every wolfSSL build on glibc was affected. Add that reserve to the thread stack when built against wolfSSL. musl puts the block beside the stack rather than inside it and needs nothing extra, and OpenSSL has no static TLS at all, so neither pays for it. Check the pthread_create() return value as well, so a thread that cannot be created reports itself and suggests stacksize instead of hanging. --- src/common.c | 2 +- src/conf.c | 7 ++++++- src/proxy.h | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/common.c b/src/common.c index ea5e472..f1a0be3 100644 --- a/src/common.c +++ b/src/common.c @@ -182,7 +182,7 @@ int timeouts[12] = { EINVAL below it and the thread silently gets the 8M system default stack. */ size_t threadstacksize(int extra){ - long size = BASESTACKSIZE + extra; + long size = BASESTACKSIZE + TLSSTACKSIZE + extra; if(size < (long)PTHREAD_STACK_MIN) size = (long)PTHREAD_STACK_MIN; return (size_t)size; diff --git a/src/conf.c b/src/conf.c index fc74b22..7486185 100644 --- a/src/conf.c +++ b/src/conf.c @@ -158,7 +158,12 @@ int start_proxy_thread(struct child * chp){ pthread_attr_init(&pa); pthread_attr_setstacksize(&pa,threadstacksize(conf.stacksize)); pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED); - pthread_create(&thread, &pa, startsrv, (void *)chp); + if(pthread_create(&thread, &pa, startsrv, (void *)chp)){ + pthread_attr_destroy(&pa); + fprintf(stderr, "Failed to create service thread on line %d, try to set larger stacksize\n", linenum); + _3proxy_sem_unlock(conf.threadinit); + return(40); + } pthread_attr_destroy(&pa); #endif _3proxy_sem_lock(conf.threadinit); diff --git a/src/proxy.h b/src/proxy.h index 7a65f75..87d405d 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -135,6 +135,23 @@ void daemonize(void); #endif #endif +/* wolfSSL reserves around 48K of static thread-local storage. glibc counts + that against the thread stack, so pthread_create() fails with EINVAL and + no thread starts at all. musl places the block next to the stack instead + of inside it and needs nothing extra, and OpenSSL has no static TLS. + musl identifies itself by no macro of its own, but it does not define + __GLIBC__, which any libc header pulled in above would have set. + */ +#ifndef TLSSTACKSIZE +#if defined(__linux__) && !defined(__GLIBC__) +#define TLSSTACKSIZE 0 +#elif defined(WITH_WOLFSSL) +#define TLSSTACKSIZE 49152 +#else +#define TLSSTACKSIZE 0 +#endif +#endif + #ifndef _WIN32 size_t threadstacksize(int extra); #endif