Skip to content

Commit 13bce27

Browse files
committed
Do not panic, maintain old behavior
1 parent f70cf59 commit 13bce27

File tree

1 file changed

+17
-25
lines changed
  • library/std/src/sys/thread_local/native

1 file changed

+17
-25
lines changed

library/std/src/sys/thread_local/native/lazy.rs

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ unsafe impl DestroyedState for () {
2222
#[derive(Copy, Clone)]
2323
enum State<D> {
2424
Uninitialized,
25-
Initializing,
2625
Alive,
2726
Destroyed(D),
2827
}
@@ -64,36 +63,31 @@ where
6463

6564
#[cold]
6665
fn get_or_init_slow(&self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
67-
// Ensure we have unique access to an uninitialized value.
6866
match self.state.get() {
69-
State::Uninitialized => self.state.set(State::Initializing),
70-
State::Initializing => panic!("thread_local initializer recursively depends on itself"),
67+
State::Uninitialized => {}
7168
State::Alive => return self.value.get().cast(),
7269
State::Destroyed(_) => return ptr::null(),
7370
}
7471

75-
struct BackToUninitOnPanic<'a, D>(&'a Cell<State<D>>);
76-
impl<'a, D> Drop for BackToUninitOnPanic<'a, D> {
77-
fn drop(&mut self) {
78-
self.0.set(State::Uninitialized);
79-
}
80-
}
81-
82-
// Get the initial value, making sure that we restore the state to uninitialized
83-
// should f panic.
84-
let on_panic = BackToUninitOnPanic(&self.state);
8572
let v = i.and_then(Option::take).unwrap_or_else(f);
86-
crate::mem::forget(on_panic);
8773

88-
// SAFETY: we are !Sync so we have exclusive access to self.value. We also ensured
89-
// that the state was uninitialized so we aren't replacing a value we must keep alive.
90-
unsafe {
91-
self.value.get().write(MaybeUninit::new(v));
74+
match self.state.replace(State::Alive) {
75+
State::Uninitialized => D::register_dtor(self),
76+
77+
State::Alive => {
78+
// An init occurred during a recursive call, this could be a panic in the future.
79+
80+
// SAFETY: we cannot be inside a `LocalKey::with` scope, as the initializer
81+
// has already returned and the next scope only starts after we return
82+
// the pointer. Therefore, there can be no references to the old value.
83+
unsafe { (*self.value.get()).assume_init_drop() }
84+
}
85+
86+
State::Destroyed(_) => unreachable!(),
9287
}
9388

94-
self.state.set(State::Alive);
95-
D::register_dtor(self);
96-
self.value.get().cast()
89+
// SAFETY: we are !Sync so we have exclusive access to self.value.
90+
unsafe { (*self.value.get()).write(v) }
9791
}
9892
}
9993

@@ -113,9 +107,7 @@ unsafe extern "C" fn destroy<T>(ptr: *mut u8) {
113107
// We also updated the state to Destroyed to prevent the destructor
114108
// from accessing the thread-local variable, as this would violate
115109
// the exclusive access provided by &mut T in Drop::drop.
116-
unsafe {
117-
crate::ptr::drop_in_place(storage.value.get().cast::<T>());
118-
}
110+
unsafe { (*storage.value.get()).assume_init_drop() }
119111
}
120112
})
121113
}

0 commit comments

Comments
 (0)