Skip to content

Commit 7c5213c

Browse files
authored
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``
2 parents cf07246 + c63b0ce commit 7c5213c

File tree

2 files changed

+12
-9
lines changed

2 files changed

+12
-9
lines changed

Diff for: library/std/src/sys/thread_local/fast_local.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::lazy::LazyKeyInner;
22
use crate::cell::Cell;
33
use crate::sys::thread_local_dtor::register_dtor;
4-
use crate::{fmt, mem, panic};
4+
use crate::{fmt, mem, panic, ptr};
55

66
#[doc(hidden)]
77
#[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) {
237237
// Wrap the call in a catch to ensure unwinding is caught in the event
238238
// a panic takes place in a destructor.
239239
if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe {
240-
let value = (*ptr).inner.take();
241-
(*ptr).dtor_state.set(DtorState::RunningOrHasRun);
240+
let Key { inner, dtor_state } = &*ptr;
241+
let value = inner.take();
242+
dtor_state.set(DtorState::RunningOrHasRun);
242243
drop(value);
243244
})) {
244245
rtabort!("thread local panicked on drop");

Diff for: library/std/src/sys/thread_local/mod.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,15 @@ mod lazy {
9191
}
9292
}
9393

94-
/// The other methods hand out references while taking &self.
95-
/// As such, callers of this method must ensure no `&` and `&mut` are
96-
/// available and used at the same time.
94+
/// Watch out: unsynchronized internal mutability!
95+
///
96+
/// # Safety
97+
/// Causes UB if any reference to the value is used after this.
9798
#[allow(unused)]
98-
pub unsafe fn take(&mut self) -> Option<T> {
99-
// SAFETY: See doc comment for this method.
100-
unsafe { (*self.inner.get()).take() }
99+
pub(crate) unsafe fn take(&self) -> Option<T> {
100+
let mutable: *mut _ = UnsafeCell::get(&self.inner);
101+
// SAFETY: That's the caller's problem.
102+
unsafe { mutable.replace(None) }
101103
}
102104
}
103105
}

0 commit comments

Comments
 (0)