Hi Achim, On Sat, 8 Nov 2025 21:01:56 +0900 Takashi Yano via Cygwin <[email protected]> wrote: > 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

