-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
thread_local destructors not called at thread exit #7096
Comments
Test program: #include <thread>
#include <string>
using namespace std;
thread_local string s("Hello");
int main()
{
thread([] {
s;
}).join();
return 0;
} If built with |
Opened upstream bug https://sourceforge.net/p/mingw-w64/bugs/859/ once I found my old sourceforge account and got the password reset |
I've been playing with this a little on and off. I pasted a patch to the mingw-w64 bug that allows their implementation to work with gcc, but I was concerned because the destructors would be run after emutls was destroyed, so all thread_locals would be NULL. Today I tried applying @lhmouse's patch from #7071 (comment) and overriding gcc/libstdc++'s configure test so it would use its implementation instead of the crt's. This also seems to work, probably at the proper time of thread tear-down. |
(commenting here also, for visibility, in addition to the mingw-w64 bugtracker); Your patch for mingw-w64 tls_atexit.c looks good and would be a good thing to have in any case. But you're right that it might be a bit problematic still when used together with emutls, as the final destructors are run after emutls has shut down. A GCC/libstdc++ option of forcing it to provide its own Regarding correctness of when destructors are executed, IIRC the GCC/libstdc++ implementation doesn't run destructors for TLS objects owned by a particular DLL when a DLL is unloaded (but running those destructors later, which can be fatal, iirc I've seen a bug report for this somewhere as well). I've got a testcase that should, hopefully, test all the various combinations of threads and DLL loading/unloading, at https://github.com/mstorsjo/llvm-mingw/blob/master/test/tlstest-lib.cpp and https://github.com/mstorsjo/llvm-mingw/blob/master/test/tlstest-main.cpp. |
I guess that explains https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/atexit_thread.cc#L153-L158
Log with current state:
Log with gcc/libstdc++'s implementation:
Log with patched mingw-w64 implementation
Log with VC2019:
|
If any static destructor is invoked prior to a TLS destructor then it would be another bug [1]. This might require mingw-w64 to override [1] https://en.cppreference.com/w/cpp/utility/program/exit: a) The last destructor for thread-local objects is sequenced-before the first destructor for a static object |
I added logs to my prior comment for VC2019 and the current unpatched state of mingw-w64. |
I stepped through the disassembly, and the tls value that mingw was storing its dtor list in was NULL at the time the tls_callback was called. It appears that emutls is cleaned up before mingw's tls_callback is called for DLL_THREAD_DETACH (3).
Verified on both i686 and x86_64.
/cc @mstorsjo author of mingw's __cxa_thread_atexit
Originally posted by @jeremyd2019 in #7071 (comment)
The text was updated successfully, but these errors were encountered: