about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorYuki Okushi <jtitor@2k36.org>2022-10-11 18:37:53 +0900
committerGitHub <noreply@github.com>2022-10-11 18:37:53 +0900
commite0954cadc8a407bed951ff8d956b76236b7dd97c (patch)
treeae1e218b65a19999e4738d28dd5ea1a6e13514f0 /library/std/src
parent387df55f2628f6ab48f578f9fde6f2e5b4f40b57 (diff)
parentb0b9f5bc269f5c5c1330bf30d25faf85741b2d49 (diff)
downloadrust-e0954cadc8a407bed951ff8d956b76236b7dd97c.tar.gz
rust-e0954cadc8a407bed951ff8d956b76236b7dd97c.zip
Rollup merge of #102412 - joboet:dont_panic, r=m-ou-se
Never panic in `thread::park` and `thread::park_timeout`

fixes #102398

`@rustbot` label +T-libs +T-libs-api
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/thread/mod.rs22
1 files changed, 20 insertions, 2 deletions
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 2de7da3793f..c29b22c69e7 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -160,7 +160,7 @@ use crate::ffi::{CStr, CString};
 use crate::fmt;
 use crate::io;
 use crate::marker::PhantomData;
-use crate::mem;
+use crate::mem::{self, forget};
 use crate::num::NonZeroU64;
 use crate::num::NonZeroUsize;
 use crate::panic;
@@ -851,10 +851,22 @@ pub fn sleep(dur: Duration) {
     imp::Thread::sleep(dur)
 }
 
+/// Used to ensure that `park` and `park_timeout` do not unwind, as that can
+/// cause undefined behaviour if not handled correctly (see #102398 for context).
+struct PanicGuard;
+
+impl Drop for PanicGuard {
+    fn drop(&mut self) {
+        rtabort!("an irrecoverable error occurred while synchronizing threads")
+    }
+}
+
 /// Blocks unless or until the current thread's token is made available.
 ///
 /// A call to `park` does not guarantee that the thread will remain parked
-/// forever, and callers should be prepared for this possibility.
+/// forever, and callers should be prepared for this possibility. However,
+/// it is guaranteed that this function will not panic (it may abort the
+/// process if the implementation encounters some rare errors).
 ///
 /// # park and unpark
 ///
@@ -939,10 +951,13 @@ pub fn sleep(dur: Duration) {
 /// [`thread::park_timeout`]: park_timeout
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn park() {
+    let guard = PanicGuard;
     // SAFETY: park_timeout is called on the parker owned by this thread.
     unsafe {
         current().inner.as_ref().parker().park();
     }
+    // No panic occurred, do not abort.
+    forget(guard);
 }
 
 /// Use [`park_timeout`].
@@ -1003,10 +1018,13 @@ pub fn park_timeout_ms(ms: u32) {
 /// ```
 #[stable(feature = "park_timeout", since = "1.4.0")]
 pub fn park_timeout(dur: Duration) {
+    let guard = PanicGuard;
     // SAFETY: park_timeout is called on the parker owned by this thread.
     unsafe {
         current().inner.as_ref().parker().park_timeout(dur);
     }
+    // No panic occurred, do not abort.
+    forget(guard);
 }
 
 ////////////////////////////////////////////////////////////////////////////////