Deadlock in cygwin1.dll when joining a thread before thread_local initialization
Tomohiro Kashiwada
tomohiro-kashiwada@ezweb.ne.jp
Thu Oct 30 11:47:05 GMT 2025
Hello,
I found a deadlock in cygwin1.dll that occurs during process cleanup.
It happens when the following conditions are met:
- A thread is launched that will initialize the thread_local slot for a
variable whose destructor is non-trivial.
- The main thread waits to join that thread during global destructor calls,
before the thread has initialized the thread_local slot.
The former condition refers to a function-scope static thread_local
variable, or a global thread_local variable whose name has not yet been
referenced by any thread.
Here is a reproducer (the same file is attached), compile with g++ 13.4.0
regardless of optimization, and run under cygwin 3.6.5-1
---------------------------------------------
#include <thread>
struct the_type {
~the_type() {}
};
struct myjthread {
template <typename F>
myjthread(F f): thr(f) {}
~myjthread() { thr.join(); }
std::thread thr;
};
thread_local the_type g_v;
int main() {
// if main thread accesses the thread_local variable first, pattern2
doesn't matter
//g_v = {};
static myjthread t([] {
//std::this_thread::sleep_for(std::chrono::seconds(1)); //< this sleep
might increase reproducibility
// pattern1: static thread_local
static thread_local the_type s_v;
// pattern2: global thread_local; its slot is allocated in this thread
//g_v = {};
});
}
---------------------------------------------
This issue was observed as a random hang in the LLVM test suite.
Although the triggering thread_local variable in LLVM can be removed, I
hope the runtime can be fixed.
Regards,
--
Tomohiro Kashiwada (@kikairoya)
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: hang-static-thread-local.cc
URL: <https://cygwin.com/pipermail/cygwin/attachments/20251030/61d644b3/attachment.cc>
More information about the Cygwin
mailing list