Guarantee needs_drop thread-local variables are destroyed at a well-defined point
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
First, some terminology. When a thread-local variable gets destroyed there are two possible relevant destructors:
- The
Dropimplementation of the type stored in the thread-local variable. I will call these "user-space" destructors, as they are defined by Rust users. - The cleanup needed by the thread-local implementation to free any related memory. I will call these "internal" destructors, as they are defined by the standard library internals.
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:
- It guarantees that if
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. - It can simplify the
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. - Because of (2) we can simplify the
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). - We can strengthen the guarantee of
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
No files, tests, or entry points are named in the issue. Start by reviewing thread-local destruction and cleanup behavior across the supported platforms, then determine whether the proposed guarantees and registry approach are feasible; done would require an agreed design and corresponding implementation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- operating-systems
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100