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)
#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 = {};
});
}
--
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