-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Run TLS destructors at process exit on all platforms #134085
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
Conversation
☔ The latest upstream changes (presumably #134108) made this pull request unmergeable. Please resolve the merge conflicts. |
This comment has been minimized.
This comment has been minimized.
62b9e7a
to
b18d55b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay, I've been quite busy recently.
At a first glance, the changes look mostly good. There is a problem with the TLS destructor registration however: the TLS key can be used as soon as it is initialized, so it is possible that another thread completes before the destructor is registered. Always registering the destructor is not an option either, since that might lead to cycles in the destructor list. Windows uses INIT_ONCE
synchronization to resolve this issue, but replicating that might prove difficult on platforms without a native Once
-like interface (Once
itself cannot be used in the TLS code since it needs TLS itself). I think this is best solved by keeping a thread-local destructor list similar to the one used on platforms with native TLS, but using the keys (or perhaps references to the LazyKey
s) instead of pointers to values. Or perhaps you can think of another way?
You are right.
I implemented it using references to |
I now have the problem that I need to register the Do you have an idea how I could achieve that without registering a second TLS key per |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I solved this by modifying This should be ready for review now. |
This comment has been minimized.
This comment has been minimized.
This calls TLS destructors for the thread that initiates a process exit. This is done by registering a process-wide exit callback. Previously UNIX platforms other than Linux and Apple did not destruct TLS variables on the thread that initiated the process exit (either by returning from main or calling std::process::exit).
I have some concerns about the implementation, but before that, I think T-libs should have a look at this to ensure that they are okay with the behaviour change: @rustbot label +I-libs-nominated |
Note that this is the same behavior as on currently stable Rust on Linux. struct Foo;
impl Drop for Foo {
fn drop(&mut self) {
println!("wut");
}
}
thread_local!(static FOO: Foo = Foo);
fn main() {
FOO.with(|_| {});
unsafe { libc::exit(0) };
} The program above will print |
We briefly discussed this in the libs meeting. We'd like to understand the motivation better. Is this just for consistency? Or are there concrete bugs that are solved by this PR? |
There are several reasons for this:
Alternative: Never Run TLS DestructorsAn alternative approach would be to never run TLS destructors on process exit. While this is not my preferred solution due to the reasons mentioned above, it would at least provide consistency and be easy to implement. This approach would also align with the behavior of |
@rustbot ready |
We discussed this again during today's libs meeting. Opinions were mixed, leaning towards close. The following issues were raised during the discussion:
Leak checking wasn't discussed, but from previous issues I have the impression that only limited effort is spent on making leak-checkers happy. Genuine leaks need to be fixed, false positives (quasi-static things) are better handled through exceptions in the leak checker. @rfcbot fcp close |
Team member @the8472 has proposed to close this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
use crate::mem; | ||
|
||
pub unsafe fn at_process_exit(cb: unsafe extern "C" fn()) { | ||
// Miri does not support atexit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you file an issue for this in the Miri repo? If std starts using this, we should consider supporting it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could use a few more comments, explaining what enable_thread / enable_process are doing. The names sound like they enable a thread/process but that's not quite right I think.
} | ||
|
||
/// On platforms with key-based TLS, the system runs the destructors for us. | ||
/// We still have to make sure that [`crate::rt::thread_cleanup`] is called, | ||
/// however. This is done by defering the execution of a TLS destructor to | ||
/// the next round of destruction inside the TLS destructors. | ||
/// | ||
/// POSIX systems do not run TLS destructors at process exit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are they guaranteed to not run? Or are they just not guaranteed to run? Does the implementation deal gracefully with implementations that run them anyway?
Oh never mind, I saw this in the FCP list but the list didn't say that this is "FCP close". |
The final comment period, with a disposition to close, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. |
This calls TLS destructors for the thread that initiates a process exit. This is done by registering a process-wide
exit callback.
Previously UNIX platforms other than Linux and Apple did not destruct TLS variables on the thread that initiated the process exit (either by returning from
main
or callingstd::process::exit
).This also adds a test to verify this behavior.
@joboet Can we run CI tests for all available platforms for this?
r? joboet