about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-04-27 07:55:38 +0200
committerGitHub <noreply@github.com>2024-04-27 07:55:38 +0200
commit7c5213cf0ab5505bfc07d0f4f1cd730bdc89699a (patch)
tree9f06e78c8c20172b76d1c31d7a2529af8eaaeb9a
parentcf07246ae9a95f7b145e8f1851723f5fe5fa0f96 (diff)
parentc63b0ceb94c4c953f080ff0c543a950737408ff7 (diff)
downloadrust-7c5213cf0ab5505bfc07d0f4f1cd730bdc89699a.tar.gz
rust-7c5213cf0ab5505bfc07d0f4f1cd730bdc89699a.zip
Rollup merge of #124387 - workingjubilee:use-raw-pointers-in-thread-locals, r=joboet
thread_local: be excruciatingly explicit in dtor code

Use raw pointers to accomplish internal mutability, and clearly split references where applicable. This reduces the likelihood that any of these parts are misunderstood, either by humans or the compiler's optimizations.

Fixes #124317

r? ``@joboet``
-rw-r--r--library/std/src/sys/thread_local/fast_local.rs7
-rw-r--r--library/std/src/sys/thread_local/mod.rs14
2 files changed, 12 insertions, 9 deletions
diff --git a/library/std/src/sys/thread_local/fast_local.rs b/library/std/src/sys/thread_local/fast_local.rs
index 69ee70de30c..49b51a729e4 100644
--- a/library/std/src/sys/thread_local/fast_local.rs
+++ b/library/std/src/sys/thread_local/fast_local.rs
@@ -1,7 +1,7 @@
 use super::lazy::LazyKeyInner;
 use crate::cell::Cell;
 use crate::sys::thread_local_dtor::register_dtor;
-use crate::{fmt, mem, panic};
+use crate::{fmt, mem, panic, ptr};
 
 #[doc(hidden)]
 #[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)]
@@ -237,8 +237,9 @@ unsafe extern "C" fn destroy_value<T>(ptr: *mut u8) {
     // Wrap the call in a catch to ensure unwinding is caught in the event
     // a panic takes place in a destructor.
     if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe {
-        let value = (*ptr).inner.take();
-        (*ptr).dtor_state.set(DtorState::RunningOrHasRun);
+        let Key { inner, dtor_state } = &*ptr;
+        let value = inner.take();
+        dtor_state.set(DtorState::RunningOrHasRun);
         drop(value);
     })) {
         rtabort!("thread local panicked on drop");
diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs
index 8b2c839f837..7500c95d8b4 100644
--- a/library/std/src/sys/thread_local/mod.rs
+++ b/library/std/src/sys/thread_local/mod.rs
@@ -91,13 +91,15 @@ mod lazy {
             }
         }
 
-        /// The other methods hand out references while taking &self.
-        /// As such, callers of this method must ensure no `&` and `&mut` are
-        /// available and used at the same time.
+        /// Watch out: unsynchronized internal mutability!
+        ///
+        /// # Safety
+        /// Causes UB if any reference to the value is used after this.
         #[allow(unused)]
-        pub unsafe fn take(&mut self) -> Option<T> {
-            // SAFETY: See doc comment for this method.
-            unsafe { (*self.inner.get()).take() }
+        pub(crate) unsafe fn take(&self) -> Option<T> {
+            let mutable: *mut _ = UnsafeCell::get(&self.inner);
+            // SAFETY: That's the caller's problem.
+            unsafe { mutable.replace(None) }
         }
     }
 }