-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
TLS destructors on the main thread are not always run #28129
Comments
The memory corruption in MacOSX seems to be related to the TLS usage during
both if |
This is part of some cleanup I did while investigating #28129. This also ensures that `on_panic` is run even if the user has registered too many callbacks.
This is mainly to avoid infinite recursion and make debugging more convenient in the anomalous case in which `on_panic` panics. I encountered such issues while changing libstd to debug/fix part of #28129. While writing this I was wondering about which functions belong to `panicking` and which to `unwind`. I placed them in this way mostly because of convenience, but I would strongly appreciate guidance.
pthread destructors seem to have the same behaviour on MacOS X as on Linux (i.e. they are not run from when the main thread terminates). Googling around seems to suggest that this is a known (expected?) fact. Specifically, TLS destructors are only run when |
Yeah I think solving this in the case of pthreads will either require us documenting "dtors may not run" or perhaps adding our own atexit handler or something like that to handle this (e.g. some custom code on our end). Not entirely sure what that would look like though! |
In order to make the Another option would be to start the The C Documenting "dtors may not run" looks like a reasonable compromise to me, especially if we can guarantee that this will at most happen for the main thread (and, ideally, only on non-Rust apps). I believe that this guarantee is especially important if threads are spawned and joined (instead of managed as a thread pool) to ensure that leaks are bounded. |
Yeah this probably isn't so bad as we already do it in some cases, so it'd just be a matter of shuffling things around.
Unfortunately I think this won't work because there's a number of GUI frameworks (or something like that) which only work on the main thread (I think on Windows in particular), so running off-the-main-thread by default may be a bit of a heavy hammer to fix this!
I agree it's probably not that bad, but if we could get OSX and Windows working reliably, it's more pressure for us to get pthreads working reliably :). I feel like Windows is pretty easy to fix, it seems like some small error is just being missed there. OSX also feels the same way to me in terms of weird things happening. The pthreads case also isn't super critical on Linux because it's only used on older linuxes. Overall I think we may still have enough rope left to climb out and close this issue, so I wouldn't be quite willing just yet to close it out by documenting things may not run. |
Windows itself does not actually care which thread you do the UI on, as long as you're consistent. Once you create a window on a given thread, that thread now has a message queue which you're obligated to pump forever. |
Just confirmed the memory corruption in the OP on OSX occurs for the same reason listed here #57534 (comment). It is not specific to the main thread. AFAICT it is UB on macos to register destructors during thread cleanup via |
…ichton OSX: fix rust-lang#57534 registering thread dtors while running thread dtors r? @alexcrichton - "fast" `thread_local` destructors get run even on the main thread - "fast" `thread_local` dtors, can initialize other `thread_local`'s One corner case where this fix doesn't work, is when a C++ `thread_local` triggers the initialization of a rust `thread_local`. I did not add any std::thread specific flag to indicate that the thread is currently exiting, which would be checked before registering a new dtor (I didn't really know where to stick that). I think this does the trick tho! Let me know if anything needs tweaking/fixing/etc. resolves this for macos: rust-lang#28129 fixes: rust-lang#57534
…ichton OSX: fix rust-lang#57534 registering thread dtors while running thread dtors r? @alexcrichton - "fast" `thread_local` destructors get run even on the main thread - "fast" `thread_local` dtors, can initialize other `thread_local`'s One corner case where this fix doesn't work, is when a C++ `thread_local` triggers the initialization of a rust `thread_local`. I did not add any std::thread specific flag to indicate that the thread is currently exiting, which would be checked before registering a new dtor (I didn't really know where to stick that). I think this does the trick tho! Let me know if anything needs tweaking/fixing/etc. resolves this for macos: rust-lang#28129 fixes: rust-lang#57534
OSX: fix #57534 registering thread dtors while running thread dtors r? @alexcrichton - "fast" `thread_local` destructors get run even on the main thread - "fast" `thread_local` dtors, can initialize other `thread_local`'s One corner case where this fix doesn't work, is when a C++ `thread_local` triggers the initialization of a rust `thread_local`. I did not add any std::thread specific flag to indicate that the thread is currently exiting, which would be checked before registering a new dtor (I didn't really know where to stick that). I think this does the trick tho! Let me know if anything needs tweaking/fixing/etc. resolves this for macos: #28129 fixes: #57534
So from the 4 items listed in the OP, the first two are fine, and the third was a separate bug that got fixed. EDIT: oh, the 2nd one is also not fine, I see. What is the situation on Windows nowadays? (Cc @retep998) |
We had some test failures because crossbeam-channel may panic when trying to call recv() during thread shutdown. This seems to be similar to this upstream bug: crossbeam-rs/crossbeam#321. Unfortunately it seems that some operating systems may tear down thread-local storage early, rust-lang/rust#28129, which can trigger panics if trying to interact with TLS during a drop. To avoid this issue, this switches from using a channel to signal the thread shutdown to just using the join handle (which we should have been doing anyway).
We had some test failures because crossbeam-channel may panic when trying to call recv() during thread shutdown. This seems to be similar to this upstream bug: crossbeam-rs/crossbeam#321. Unfortunately it seems that some operating systems may tear down thread-local storage early, rust-lang/rust#28129, which can trigger panics if trying to interact with TLS during a drop. To avoid this issue, this switches from using a channel to signal the thread shutdown to just using the join handle (which we should have been doing anyway).
We had some test failures because crossbeam-channel may panic when trying to call recv() during thread shutdown. This seems to be similar to this upstream bug: crossbeam-rs/crossbeam#321. Unfortunately it seems that some operating systems may tear down thread-local storage early, rust-lang/rust#28129, which can trigger panics if trying to interact with TLS during a drop. To avoid this issue, this switches from using a channel to signal the thread shutdown to just using the join handle (which we should have been doing anyway).
Calling Rust from a GCC destructor can result in panics when using pthreads (rust-lang/rust#28129) Move client request code to a separate thread to work around this issue Signed-off-by: Kostis Papazafeiropoulos <papazof@gmail.com>
Calling Rust from a GCC destructor can result in panics when using pthreads (rust-lang/rust#28129) Move client request code to a separate thread to work around this issue Signed-off-by: Kostis Papazafeiropoulos <papazof@gmail.com>
Calling Rust from a GCC destructor can result in panics when using pthreads (rust-lang/rust#28129) Move client request code to a separate thread to work around this issue Signed-off-by: Kostis Papazafeiropoulos <papazof@gmail.com>
It seems we do not, but rather, we currently effectively require libc support to include thread-local support. |
@workingjubilee I confirmed that emutls on android will print "wut". |
Thank you! It seems this is resolved then? Hopefully? |
I am a bit confused by the macos sitaution: I don't see how the simple program above could be affected by #57655. Very strange. 🤷 Do we have a test checking that main thread destructors run? Reopening as needs-test. |
PR with a test is up: #126829 (I couldn't find an existing test.) |
…ubilee add test for main thread thread-local destructors Fixes rust-lang#28129
…ubilee add test for main thread thread-local destructors Fixes rust-lang#28129
Turns out musl is still broken, I opened a new issue for that: #126858. |
…ubilee add test for main thread thread-local destructors Fixes rust-lang#28129
…ubilee add test for main thread thread-local destructors Fixes rust-lang#28129
…ubilee add test for main thread thread-local destructors Fixes rust-lang#28129
I gave up on the PR since even some glibc targets are effected (including the one we test on CI), so now we have two issues tracking the same thing -- this and #126858. EDIT: I have closed the other issue. |
Calling Rust from a GCC destructor can result in panics when using pthreads (rust-lang/rust#28129) Move client request code to a separate thread to work around this issue Signed-off-by: Kostis Papazafeiropoulos <papazof@gmail.com>
Testing on FreeBSD 14 shows that TLS destructors are not run for the main thread. |
There are some platforms where TLS destructors are run when the main thread exits, and there are some platforms where this does not happen,~~ and there are some platforms where things just go crazy ~~. For example, testing this program:
This should print
Foo dtor
, but prints nothing on some targets:Here's a more complicated testcase that also involves initializing a destructor while destructors are being run; ideally this will be added to the test suite at some point:
some older notes
appears to call destructors, but the program above specifically causes some form of memory corrupting, triggering an assert in mallocfixed by OSX: fix #57534 registering thread dtors while running thread dtors #57655notwork.We're listening forDLL_PROCESS_DETACH
but for some reason we're not getting that notification.The text was updated successfully, but these errors were encountered: