Hi everyone, I encountered a problem with static thread_local in C++ program. The following simple reproducer does not work as expected if it runs under cygwin 3.7.0 (Test), while it works under cygwin 3.6.5.
To conclude, this was not a bug in Cygwin 3.7.0. This is triggered by the commit: commit ebd92b128f62a0b3c270319487b8486abdfa405b Author: Takashi Yano <[email protected]> Date: Fri Apr 4 21:22:27 2025 +0900 Cygwin: thread: Use simple array instead of List<pthread_key> where the call order of the destructors for pthread_key was changed. The call order can depend on implementation. So the code using pthread_key should not expect any predetermined call order of the destuctors. The result of the following code is 1: 0xa00016938 2: 0xa00016b98 X::print(): 2 X::print(): 1 X::~X(): 1 X::~X(): 2 under cygwin 3.6.5, while it is 1: 0xa00016938 2: 0xa00016b98 X::print(): 2 X::print(): 1 X::~X(): 2133815816 X::~X(): 2133815816 under cygwin 3.7.0 (Test). I looked into the problem, and found that the executable for the following code registers two pthread_keys with each destructor; one is void emutls_destroy(void *ptr) in libgcc/emutls.c, and the other is void run(void *p) in libstdc++-v3/libsupc++/atexit_thread.cc. emutls_destroy() free's the memory erea of static thread_local X, that is accessed from X::~X() which is called from run(). As a result, if the emutls_destroy() is called before run(), run() referres to the memory erea already free'ed. I think this is a bug of gcc. This issue does not occur in Linux, because Linux does not use emutls. Any idea? #include <thread> #include <cstdio> #include <unistd.h> class X { int n; public: X(int n1) : n(n1) {} ~X() { printf("X::~X(): %d\n", n); } void print() { printf("X::print(): %d\n", n); } }; void func(int n) { static thread_local X x(n); printf("%d: %p\n", n, &x); usleep(10000); x.print(); usleep(10000); } int main() { std::thread t1(func, 1); std::thread t2(func, 2); t1.join(); t2.join(); return 0; } Any idea? -- Takashi Yano <[email protected]> -- Problem reports: https://cygwin.com/problems.html FAQ: https://cygwin.com/faq/ Documentation: https://cygwin.com/docs.html Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple

