-
-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Guarantee needs_drop thread-local variables are destroyed at a well-defined point #147342
Copy link
Copy link
Open
Labels
A-destructorsArea: Destructors (`Drop`, …)Area: Destructors (`Drop`, …)A-thread-localsArea: Thread local storage (TLS)Area: Thread local storage (TLS)C-discussionCategory: Discussion or questions that doesn't represent real issues.Category: Discussion or questions that doesn't represent real issues.T-langRelevant to the language teamRelevant to the language teamT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.
Metadata
Metadata
Assignees
Labels
A-destructorsArea: Destructors (`Drop`, …)Area: Destructors (`Drop`, …)A-thread-localsArea: Thread local storage (TLS)Area: Thread local storage (TLS)C-discussionCategory: Discussion or questions that doesn't represent real issues.Category: Discussion or questions that doesn't represent real issues.T-langRelevant to the language teamRelevant to the language teamT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.
Type
Fields
Give feedbackNo fields configured for issues without a type.
First, some terminology. When a thread-local variable gets destroyed there are two possible relevant destructors:
Dropimplementation of the type stored in the thread-local variable. I will call these "user-space" destructors, as they are defined by Rust users.I've noticed that on some platforms we leave the moment when TLS variables are destroyed entirely up to the operating system/pthread implementation, for both user-space destructors as well as the internal destructors, whereas on other platforms we have an explicit destructor registry system where user-space destructors are registered to be called during thread clean-up.
I propose we instead always use a registry system for user-space destructors on all platforms, and call them at a well-defined point during thread clean-up. This has several advantages:
needs_drop::<T>()is false for some thread-local variable, thenLocalKey::withcan never fail (assuming the constructor doesn't panic), even when user-space TLS destructors are being ran. This is of potential interest to global allocators, which are regularly called in other user-space destructors.std::thread::currentimplementation which currently has to handle the case where its thread-local storage has been cleaned up already, meaning it has to synthesize a newThreadhandle.std::thread::Threadhandle implementation to have a single shared canonical handle per thread. This allows us to implement extra functionality which was previously impossible/impractical, such asThread::is_finishedto see if a thread is truly finished just from its handle (which can be shared and passed around, unlikeJoinHandle).std::thread::JoinHandle::is_finishedsuch that it only returns true if truly all user-defined Rust code on that thread has finished running - currently it only claimsmainis done.@joboet Since this is your area of expertise I would be interested to hear your thoughts.