Skip to content
/ rust Public
forked from rust-lang/rust

Commit

Permalink
Rollup merge of rust-lang#124387 - workingjubilee:use-raw-pointers-in…
Browse files Browse the repository at this point in the history
…-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 rust-lang#124317

r? `@joboet`
  • Loading branch information
jhpratt authored Apr 27, 2024
2 parents 185c80f + c63b0ce commit 5045321
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 9 deletions.
7 changes: 4 additions & 3 deletions library/std/src/sys/thread_local/fast_local.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -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");
Expand Down
14 changes: 8 additions & 6 deletions library/std/src/sys/thread_local/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
}
}
}
Expand Down

0 comments on commit 5045321

Please sign in to comment.