Skip to content

Commit c3190c1

Browse files
committed
Auto merge of #90442 - ChrisDenton:win-tls-dtor, r=alexcrichton
Windows thread-local keyless drop `#[thread_local]` allows us to maintain a per-thread list of destructors. This also avoids the need to synchronize global data (which is particularly tricky within the TLS callback function). r? `@alexcrichton`
2 parents 6384dca + 1048651 commit c3190c1

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

Diff for: library/std/src/sys/windows/thread_local_dtor.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
1+
//! Implements thread-local destructors that are not associated with any
2+
//! particular data.
3+
14
#![unstable(feature = "thread_local_internals", issue = "none")]
25
#![cfg(target_thread_local)]
36

4-
pub use crate::sys_common::thread_local_dtor::register_dtor_fallback as register_dtor;
7+
// Using a per-thread list avoids the problems in synchronizing global state.
8+
#[thread_local]
9+
static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
10+
11+
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
12+
DESTRUCTORS.push((t, dtor));
13+
}
14+
15+
/// Runs destructors. This should not be called until thread exit.
16+
pub unsafe fn run_keyless_dtors() {
17+
// Drop all the destructors.
18+
//
19+
// Note: While this is potentially an infinite loop, it *should* be
20+
// the case that this loop always terminates because we provide the
21+
// guarantee that a TLS key cannot be set after it is flagged for
22+
// destruction.
23+
while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
24+
(dtor)(ptr);
25+
}
26+
// We're done so free the memory.
27+
DESTRUCTORS = Vec::new();
28+
}

Diff for: library/std/src/sys/windows/thread_local_key.rs

+2
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD, c::
196196
unsafe extern "system" fn on_tls_callback(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID) {
197197
if dwReason == c::DLL_THREAD_DETACH || dwReason == c::DLL_PROCESS_DETACH {
198198
run_dtors();
199+
#[cfg(target_thread_local)]
200+
super::thread_local_dtor::run_keyless_dtors();
199201
}
200202

201203
// See comments above for what this is doing. Note that we don't need this

0 commit comments

Comments
 (0)