-
-
Notifications
You must be signed in to change notification settings - Fork 15.6k
Inappropriate panic!s in Thread::new on certain unix platforms #160793
Copy link
Copy link
Open
Labels
A-global-allocator-reentryArea: cases where global allocators should not be used, but areArea: cases where global allocators should not be used, but areA-threadArea: `std::thread`Area: `std::thread`C-bugCategory: This is a bug.Category: This is a bug.I-memleakIssue: Runtime memory leak without `mem::forget`.Issue: Runtime memory leak without `mem::forget`.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityHigh priorityT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.
Description
Activity
Metadata
Metadata
Assignees
Labels
A-global-allocator-reentryArea: cases where global allocators should not be used, but areArea: cases where global allocators should not be used, but areA-threadArea: `std::thread`Area: `std::thread`C-bugCategory: This is a bug.Category: This is a bug.I-memleakIssue: Runtime memory leak without `mem::forget`.Issue: Runtime memory leak without `mem::forget`.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityHigh priorityT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.
Found after discussing code surrounding #160219 on zulip.
Edit: It is inappropriate for
Thread::newto ever panic, because we guarantee thatthread::current, which uses it, does not call the global allocator reentrantly. The memory leak on unwind, which this issue was originally about, is not that important.The implementation of
Thread::newmanually initializes a struct behindMaybeUninit, which means that ifParker::new_in_placeunwinds, thename's memory (essentiallyOption<CString>), now held by the previously writtennamefield behindMaybeUninit, is leaked.rust/library/std/src/thread/thread.rs
Lines 101 to 108 in 4667d75
Note that this is possible, on certain unix platforms:
rust/library/std/src/sys/sync/thread_parking/pthread.rs
Lines 24 to 32 in 4667d75
which calls
rust/library/std/src/sys/pal/unix/sync/condvar.rs
Lines 152 to 175 in 4667d75
which uses
assert_eqto ensure that the initialization of theCondvarsucceeds (it can fail, e.g. from resource exhaustion). Note that the method itself expects failures are possible here. It uses a guard struct to ensure that the resources of the condattr are not leaked on unwind.Furthermore, the implementation of
std::thread::currentseems to assume thatThread::newnever unwinds, because it sets a flag to detect reentrance, which is never reset if an unwind occurs:rust/library/std/src/thread/current.rs
Lines 289 to 301 in 4667d75
The first issue should be fixable by reordering the fields' initialization logic, and the second one by adding a drop guard that unsets the busy state.