diff options
Diffstat (limited to 'library/std/src/thread')
-rw-r--r-- | library/std/src/thread/local.rs | 23 | ||||
-rw-r--r-- | library/std/src/thread/local/tests.rs | 22 | ||||
-rw-r--r-- | library/std/src/thread/mod.rs | 26 |
3 files changed, 43 insertions, 28 deletions
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 5d267891b..b30bb7b77 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -905,9 +905,8 @@ pub mod statik { pub mod fast { use super::lazy::LazyKeyInner; use crate::cell::Cell; - use crate::fmt; - use crate::mem; use crate::sys::thread_local_dtor::register_dtor; + use crate::{fmt, mem, panic}; #[derive(Copy, Clone)] enum DtorState { @@ -950,7 +949,7 @@ pub mod fast { // note that this is just a publicly-callable function only for the // const-initialized form of thread locals, basically a way to call the - // free `register_dtor` function defined elsewhere in libstd. + // free `register_dtor` function defined elsewhere in std. pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { unsafe { register_dtor(a, dtor); @@ -1028,10 +1027,15 @@ pub mod fast { // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This // causes future calls to `get` to run `try_initialize_drop` again, // which will now fail, and return `None`. - unsafe { + // + // 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); drop(value); + })) { + rtabort!("thread local panicked on drop"); } } } @@ -1044,10 +1048,8 @@ pub mod fast { pub mod os { use super::lazy::LazyKeyInner; use crate::cell::Cell; - use crate::fmt; - use crate::marker; - use crate::ptr; use crate::sys_common::thread_local_key::StaticKey as OsStaticKey; + use crate::{fmt, marker, panic, ptr}; /// Use a regular global static to store this key; the state provided will then be /// thread-local. @@ -1137,12 +1139,17 @@ pub mod os { // // Note that to prevent an infinite loop we reset it back to null right // before we return from the destructor ourselves. - unsafe { + // + // 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(|| unsafe { let ptr = Box::from_raw(ptr as *mut Value<T>); let key = ptr.key; key.os.set(ptr::invalid_mut(1)); drop(ptr); key.os.set(ptr::null_mut()); + }) { + rtabort!("thread local panicked on drop"); } } } diff --git a/library/std/src/thread/local/tests.rs b/library/std/src/thread/local/tests.rs index 80dc4c038..964c7fc5b 100644 --- a/library/std/src/thread/local/tests.rs +++ b/library/std/src/thread/local/tests.rs @@ -23,11 +23,11 @@ impl Signal { } } -struct Foo(Signal); +struct NotifyOnDrop(Signal); -impl Drop for Foo { +impl Drop for NotifyOnDrop { fn drop(&mut self) { - let Foo(ref f) = *self; + let NotifyOnDrop(ref f) = *self; f.notify(); } } @@ -82,18 +82,18 @@ fn states() { #[test] fn smoke_dtor() { - thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell::new(None)); + thread_local!(static FOO: UnsafeCell<Option<NotifyOnDrop>> = UnsafeCell::new(None)); run(&FOO); - thread_local!(static FOO2: UnsafeCell<Option<Foo>> = const { UnsafeCell::new(None) }); + thread_local!(static FOO2: UnsafeCell<Option<NotifyOnDrop>> = const { UnsafeCell::new(None) }); run(&FOO2); - fn run(key: &'static LocalKey<UnsafeCell<Option<Foo>>>) { + fn run(key: &'static LocalKey<UnsafeCell<Option<NotifyOnDrop>>>) { let signal = Signal::default(); let signal2 = signal.clone(); let t = thread::spawn(move || unsafe { let mut signal = Some(signal2); key.with(|f| { - *f.get() = Some(Foo(signal.take().unwrap())); + *f.get() = Some(NotifyOnDrop(signal.take().unwrap())); }); }); signal.wait(); @@ -187,13 +187,13 @@ fn self_referential() { fn dtors_in_dtors_in_dtors() { struct S1(Signal); thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None)); - thread_local!(static K2: UnsafeCell<Option<Foo>> = UnsafeCell::new(None)); + thread_local!(static K2: UnsafeCell<Option<NotifyOnDrop>> = UnsafeCell::new(None)); impl Drop for S1 { fn drop(&mut self) { let S1(ref signal) = *self; unsafe { - let _ = K2.try_with(|s| *s.get() = Some(Foo(signal.clone()))); + let _ = K2.try_with(|s| *s.get() = Some(NotifyOnDrop(signal.clone()))); } } } @@ -211,13 +211,13 @@ fn dtors_in_dtors_in_dtors() { fn dtors_in_dtors_in_dtors_const_init() { struct S1(Signal); thread_local!(static K1: UnsafeCell<Option<S1>> = const { UnsafeCell::new(None) }); - thread_local!(static K2: UnsafeCell<Option<Foo>> = const { UnsafeCell::new(None) }); + thread_local!(static K2: UnsafeCell<Option<NotifyOnDrop>> = const { UnsafeCell::new(None) }); impl Drop for S1 { fn drop(&mut self) { let S1(ref signal) = *self; unsafe { - let _ = K2.try_with(|s| *s.get() = Some(Foo(signal.clone()))); + let _ = K2.try_with(|s| *s.get() = Some(NotifyOnDrop(signal.clone()))); } } } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 34bdb8bd4..692ff0cbc 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -173,10 +173,16 @@ use crate::sync::Arc; use crate::sys::thread as imp; use crate::sys_common::thread; use crate::sys_common::thread_info; -use crate::sys_common::thread_parker::Parker; +use crate::sys_common::thread_parking::Parker; use crate::sys_common::{AsInner, IntoInner}; use crate::time::Duration; +#[stable(feature = "scoped_threads", since = "1.63.0")] +mod scoped; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +pub use scoped::{scope, Scope, ScopedJoinHandle}; + //////////////////////////////////////////////////////////////////////////////// // Thread-local storage //////////////////////////////////////////////////////////////////////////////// @@ -184,12 +190,6 @@ use crate::time::Duration; #[macro_use] mod local; -#[stable(feature = "scoped_threads", since = "1.63.0")] -mod scoped; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -pub use scoped::{scope, Scope, ScopedJoinHandle}; - #[stable(feature = "rust1", since = "1.0.0")] pub use self::local::{AccessError, LocalKey}; @@ -209,7 +209,6 @@ pub use self::local::{AccessError, LocalKey}; ))] #[doc(hidden)] pub use self::local::fast::Key as __FastLocalKeyInner; - // when building for tests, use real std's type #[unstable(feature = "libstd_thread_internals", issue = "none")] #[cfg(test)] @@ -220,12 +219,21 @@ pub use self::local::fast::Key as __FastLocalKeyInner; pub use realstd::thread::__FastLocalKeyInner; #[unstable(feature = "libstd_thread_internals", issue = "none")] +#[cfg(not(test))] #[cfg(all( not(target_thread_local), not(all(target_family = "wasm", not(target_feature = "atomics"))), ))] #[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner; +// when building for tests, use real std's type +#[unstable(feature = "libstd_thread_internals", issue = "none")] +#[cfg(test)] +#[cfg(all( + not(target_thread_local), + not(all(target_family = "wasm", not(target_feature = "atomics"))), +))] +pub use realstd::thread::__OsLocalKeyInner; #[unstable(feature = "libstd_thread_internals", issue = "none")] #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] @@ -1216,7 +1224,7 @@ impl Thread { let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); addr_of_mut!((*ptr).name).write(name); addr_of_mut!((*ptr).id).write(ThreadId::new()); - Parker::new(addr_of_mut!((*ptr).parker)); + Parker::new_in_place(addr_of_mut!((*ptr).parker)); Pin::new_unchecked(arc.assume_init()) }; |