aboutsummaryrefslogtreecommitdiff
path: root/src/thread.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/thread.rs')
-rw-r--r--src/thread.rs79
1 files changed, 49 insertions, 30 deletions
diff --git a/src/thread.rs b/src/thread.rs
index 7446454..b2e063a 100644
--- a/src/thread.rs
+++ b/src/thread.rs
@@ -84,7 +84,7 @@
//! tricky because argument `s` lives *inside* the invocation of `thread::scope()` and as such
//! cannot be borrowed by scoped threads:
//!
-//! ```compile_fail,E0373,E0521
+//! ```compile_fail,E0521
//! use crossbeam_utils::thread;
//!
//! thread::scope(|s| {
@@ -120,7 +120,6 @@ use std::sync::{Arc, Mutex};
use std::thread;
use crate::sync::WaitGroup;
-use cfg_if::cfg_if;
type SharedVec<T> = Arc<Mutex<Vec<T>>>;
type SharedOption<T> = Arc<Mutex<Option<T>>>;
@@ -152,6 +151,15 @@ pub fn scope<'env, F, R>(f: F) -> thread::Result<R>
where
F: FnOnce(&Scope<'env>) -> R,
{
+ struct AbortOnPanic;
+ impl Drop for AbortOnPanic {
+ fn drop(&mut self) {
+ if thread::panicking() {
+ std::process::abort();
+ }
+ }
+ }
+
let wg = WaitGroup::new();
let scope = Scope::<'env> {
handles: SharedVec::default(),
@@ -162,6 +170,10 @@ where
// Execute the scoped function, but catch any panics.
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| f(&scope)));
+ // If an unwinding panic occurs before all threads are joined
+ // promote it to an aborting panic to prevent any threads from escaping the scope.
+ let guard = AbortOnPanic;
+
// Wait until all nested scopes are dropped.
drop(scope.wait_group);
wg.wait();
@@ -177,6 +189,8 @@ where
.filter_map(|handle| handle.join().err())
.collect();
+ mem::forget(guard);
+
// If `f` has panicked, resume unwinding.
// If any of the child threads have panicked, return the panic errors.
// Otherwise, everything is OK and return the result of `f`.
@@ -547,37 +561,42 @@ impl<T> ScopedJoinHandle<'_, T> {
}
}
-cfg_if! {
- if #[cfg(unix)] {
- use std::os::unix::thread::{JoinHandleExt, RawPthread};
-
- impl<T> JoinHandleExt for ScopedJoinHandle<'_, T> {
- fn as_pthread_t(&self) -> RawPthread {
- // Borrow the handle. The handle will surely be available because the root scope waits
- // for nested scopes before joining remaining threads.
- let handle = self.handle.lock().unwrap();
- handle.as_ref().unwrap().as_pthread_t()
- }
- fn into_pthread_t(self) -> RawPthread {
- self.as_pthread_t()
- }
+/// Unix-specific extensions.
+#[cfg(unix)]
+mod unix {
+ use super::ScopedJoinHandle;
+ use std::os::unix::thread::{JoinHandleExt, RawPthread};
+
+ impl<T> JoinHandleExt for ScopedJoinHandle<'_, T> {
+ fn as_pthread_t(&self) -> RawPthread {
+ // Borrow the handle. The handle will surely be available because the root scope waits
+ // for nested scopes before joining remaining threads.
+ let handle = self.handle.lock().unwrap();
+ handle.as_ref().unwrap().as_pthread_t()
}
- } else if #[cfg(windows)] {
- use std::os::windows::io::{AsRawHandle, IntoRawHandle, RawHandle};
-
- impl<T> AsRawHandle for ScopedJoinHandle<'_, T> {
- fn as_raw_handle(&self) -> RawHandle {
- // Borrow the handle. The handle will surely be available because the root scope waits
- // for nested scopes before joining remaining threads.
- let handle = self.handle.lock().unwrap();
- handle.as_ref().unwrap().as_raw_handle()
- }
+ fn into_pthread_t(self) -> RawPthread {
+ self.as_pthread_t()
}
+ }
+}
+/// Windows-specific extensions.
+#[cfg(windows)]
+mod windows {
+ use super::ScopedJoinHandle;
+ use std::os::windows::io::{AsRawHandle, IntoRawHandle, RawHandle};
+
+ impl<T> AsRawHandle for ScopedJoinHandle<'_, T> {
+ fn as_raw_handle(&self) -> RawHandle {
+ // Borrow the handle. The handle will surely be available because the root scope waits
+ // for nested scopes before joining remaining threads.
+ let handle = self.handle.lock().unwrap();
+ handle.as_ref().unwrap().as_raw_handle()
+ }
+ }
- impl<T> IntoRawHandle for ScopedJoinHandle<'_, T> {
- fn into_raw_handle(self) -> RawHandle {
- self.as_raw_handle()
- }
+ impl<T> IntoRawHandle for ScopedJoinHandle<'_, T> {
+ fn into_raw_handle(self) -> RawHandle {
+ self.as_raw_handle()
}
}
}