about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/std/src/lib.rs10
-rw-r--r--library/std/src/thread/mod.rs40
2 files changed, 26 insertions, 24 deletions
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index c35389d44f9..232b6623078 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -363,6 +363,11 @@ extern crate std as realstd;
 #[macro_use]
 mod macros;
 
+// The runtime entry point and a few unstable public functions used by the
+// compiler
+#[macro_use]
+pub mod rt;
+
 // The Rust prelude
 pub mod prelude;
 
@@ -547,11 +552,6 @@ pub mod arch {
 #[stable(feature = "simd_x86", since = "1.27.0")]
 pub use std_detect::is_x86_feature_detected;
 
-// The runtime entry point and a few unstable public functions used by the
-// compiler
-#[macro_use]
-pub mod rt;
-
 // Platform-abstraction modules
 mod sys;
 mod sys_common;
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 56baa7e4455..74b29454b94 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -1287,29 +1287,31 @@ unsafe impl<'scope, T: Sync> Sync for Packet<'scope, T> {}
 
 impl<'scope, T> Drop for Packet<'scope, T> {
     fn drop(&mut self) {
+        // If this packet was for a thread that ran in a scope, the thread
+        // panicked, and nobody consumed the panic payload, we make sure
+        // the scope function will panic.
+        let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_)));
+        // Drop the result without causing unwinding.
+        // This is only relevant for threads that aren't join()ed, as
+        // join() will take the `result` and set it to None, such that
+        // there is nothing left to drop here.
+        // If this panics, we should handle that, because we're outside the
+        // outermost `catch_unwind` of our thread.
+        // We just abort in that case, since there's nothing else we can do.
+        // (And even if we tried to handle it somehow, we'd also need to handle
+        // the case where the panic payload we get out of it also panics on
+        // drop, and so on. See issue #86027.)
+        if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| {
+            *self.result.get_mut() = None;
+        })) {
+            rtabort!("thread result panicked on drop");
+        }
         // Book-keeping so the scope knows when it's done.
         if let Some(scope) = self.scope {
-            // If this packet was for a thread that ran in a scope, the thread
-            // panicked, and nobody consumed the panic payload, we make sure
-            // the scope function will panic.
-            let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_)));
-            // Drop the result before decrementing the number of running
-            // threads, because the Drop implementation might still use things
-            // it borrowed from 'scope.
-            // This is only relevant for threads that aren't join()ed, as
-            // join() will take the `result` and set it to None, such that
-            // there is nothing left to drop here.
-            // If this drop panics, that just results in an abort, because
-            // we're outside of the outermost `catch_unwind` of our thread.
-            // The same happens for detached non-scoped threads when dropping
-            // their ignored return value (or panic payload) panics, so
-            // there's no need to try to do anything better.
-            // (And even if we tried to handle it, we'd also need to handle
-            // the case where the panic payload we get out of it also panics
-            // on drop, and so on. See issue #86027.)
-            *self.result.get_mut() = None;
             // Now that there will be no more user code running on this thread
             // that can use 'scope, mark the thread as 'finished'.
+            // It's important we only do this after the `result` has been dropped,
+            // since dropping it might still use things it borrowed from 'scope.
             scope.decrement_num_running_threads(unhandled_panic);
         }
     }