]> git.lizzy.rs Git - rust.git/blobdiff - src/libpanic_unwind/seh.rs
Abort if C++ tries to swallow a Rust panic
[rust.git] / src / libpanic_unwind / seh.rs
index 417de8e23cc9b466adb1d4fe4b749e91240b31fc..d9dca2c0f4f479e6319a3fd750b260b2e1666be0 100644 (file)
@@ -218,31 +218,35 @@ pub struct _TypeDescriptor {
 //
 // Note that x86 Windows uses the "thiscall" calling convention for C++ member
 // functions instead of the default "C" calling convention.
-cfg_if::cfg_if! {
-    if #[cfg(target_arch = "x86")] {
-        unsafe extern "thiscall" fn exception_cleanup(e: *mut [u64; 2]) {
-            if (*e)[0] != 0 {
-                cleanup(*e);
-            }
-        }
-        unsafe extern "thiscall" fn exception_copy(_dest: *mut [u64; 2],
-                                                   _src: *mut [u64; 2])
-                                                   -> *mut [u64; 2] {
-            panic!("Rust panics cannot be copied");
-        }
-    } else {
-        unsafe extern "C" fn exception_cleanup(e: *mut [u64; 2]) {
+//
+// The exception_copy function is a bit special here: it is invoked by the MSVC
+// runtime under a try/catch block and the panic that we generate here will be
+// used as the result of the exception copy. This is used by the C++ runtime to
+// support capturing exceptions with std::exception_ptr, which we can't support
+// because Box<dyn Any> isn't clonable.
+macro_rules! define_cleanup {
+    ($abi:tt) => {
+        unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) {
             if (*e)[0] != 0 {
                 cleanup(*e);
+                super::__rust_drop_panic();
             }
         }
-        unsafe extern "C" fn exception_copy(_dest: *mut [u64; 2],
-                                            _src: *mut [u64; 2])
-                                            -> *mut [u64; 2] {
+        #[unwind(allowed)]
+        unsafe extern $abi fn exception_copy(_dest: *mut [u64; 2],
+                                             _src: *mut [u64; 2])
+                                             -> *mut [u64; 2] {
             panic!("Rust panics cannot be copied");
         }
     }
 }
+cfg_if::cfg_if! {
+   if #[cfg(target_arch = "x86")] {
+       define_cleanup!("thiscall");
+   } else {
+       define_cleanup!("C");
+   }
+}
 
 pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     use core::intrinsics::atomic_store;