about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChris Denton <christophersdenton@gmail.com>2021-11-01 15:05:57 +0000
committerChris Denton <christophersdenton@gmail.com>2021-11-01 15:19:49 +0000
commit1048651fa3d0c8d5ac98a616810d1cf2b1fe80c0 (patch)
treef4d5e469d006cad7f8eabbe54f93b1a2be7993b2
parent9212f4070ecaf4277de5f268f2ddfe56585be745 (diff)
downloadrust-1048651fa3d0c8d5ac98a616810d1cf2b1fe80c0.tar.gz
rust-1048651fa3d0c8d5ac98a616810d1cf2b1fe80c0.zip
Run destructors from existing tls callback
-rw-r--r--library/std/src/sys/windows/thread_local_dtor.rs35
-rw-r--r--library/std/src/sys/windows/thread_local_key.rs2
2 files changed, 14 insertions, 23 deletions
diff --git a/library/std/src/sys/windows/thread_local_dtor.rs b/library/std/src/sys/windows/thread_local_dtor.rs
index bf865e0fd72..25d1c6e8e87 100644
--- a/library/std/src/sys/windows/thread_local_dtor.rs
+++ b/library/std/src/sys/windows/thread_local_dtor.rs
@@ -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]
@@ -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();
 }
diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs
index 0bc51114665..ec670238e6f 100644
--- a/library/std/src/sys/windows/thread_local_key.rs
+++ b/library/std/src/sys/windows/thread_local_key.rs
@@ -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