Skip to content

Commit

Permalink
Run destructors from existing tls callback
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisDenton committed Nov 1, 2021
1 parent 9212f40 commit 1048651
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 23 deletions.
35 changes: 12 additions & 23 deletions library/std/src/sys/windows/thread_local_dtor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#![unstable(feature = "thread_local_internals", issue = "none")]
#![cfg(target_thread_local)]
use super::c;

// Using a per-thread list avoids the problems in synchronizing global state.
#[thread_local]
Expand All @@ -13,27 +12,17 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
DESTRUCTORS.push((t, dtor));
}

// See windows/thread_local_keys.rs for an explanation of this callback function.
// The short version is that all the function pointers in the `.CRT$XL*` array
// will be called whenever a thread or process starts or ends.

#[link_section = ".CRT$XLD"]
#[doc(hidden)]
#[used]
pub static TLS_CALLBACK: unsafe extern "system" fn(c::LPVOID, c::DWORD, c::LPVOID) = tls_callback;

unsafe extern "system" fn tls_callback(_: c::LPVOID, reason: c::DWORD, _: c::LPVOID) {
if reason == c::DLL_THREAD_DETACH || reason == c::DLL_PROCESS_DETACH {
// Drop all the destructors.
//
// Note: While this is potentially an infinite loop, it *should* be
// the case that this loop always terminates because we provide the
// guarantee that a TLS key cannot be set after it is flagged for
// destruction.
while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
(dtor)(ptr);
}
// We're done so free the memory.
DESTRUCTORS.shrink_to_fit();
/// Runs destructors. This should not be called until thread exit.
pub unsafe fn run_keyless_dtors() {
// Drop all the destructors.
//
// Note: While this is potentially an infinite loop, it *should* be
// the case that this loop always terminates because we provide the
// guarantee that a TLS key cannot be set after it is flagged for
// destruction.
while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
(dtor)(ptr);
}
// We're done so free the memory.
DESTRUCTORS = Vec::new();
}
2 changes: 2 additions & 0 deletions library/std/src/sys/windows/thread_local_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD, c::
unsafe extern "system" fn on_tls_callback(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID) {
if dwReason == c::DLL_THREAD_DETACH || dwReason == c::DLL_PROCESS_DETACH {
run_dtors();
#[cfg(target_thread_local)]
super::thread_local_dtor::run_keyless_dtors();
}

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

0 comments on commit 1048651

Please sign in to comment.