throw;
}
}
+
+ void swallow_exception(void (*cb)()) {
+ try {
+ // Do a rethrow to ensure that the exception is only dropped once.
+ // This is necessary since we don't support copying exceptions.
+ try {
+ cb();
+ } catch (...) {
+ println("rethrowing Rust panic");
+ throw;
+ };
+ } catch (rust_panic e) {
+ assert(false && "shouldn't be able to catch a rust panic");
+ } catch (...) {
+ println("swallowing foreign exception in catch (...)");
+ }
+ }
}
// For linking libstdc++ on MinGW
#![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))]
-
#![feature(unwind_attributes)]
use std::panic::{catch_unwind, AssertUnwindSafe};
extern "C" {
fn throw_cxx_exception();
+ fn swallow_exception(cb: extern "C" fn());
+
#[unwind(allowed)]
fn cxx_catch_callback(cb: extern "C" fn(), ok: *mut bool);
}
assert!(cxx_ok);
}
+fn check_exception_drop() {
+ static mut DROP_COUNT: usize = 0;
+
+ struct CountDrop;
+ impl Drop for CountDrop {
+ fn drop(&mut self) {
+ println!("CountDrop::drop");
+ unsafe {
+ DROP_COUNT += 1;
+ }
+ }
+ }
+
+
+ #[unwind(allowed)]
+ extern "C" fn callback() {
+ println!("throwing rust panic #2");
+ panic!(CountDrop);
+ }
+
+ unsafe {
+ swallow_exception(callback);
+ assert_eq!(DROP_COUNT, 1);
+ }
+}
+
fn main() {
unsafe { throw_cxx_exception() };
throw_rust_panic();
+ check_exception_drop();
}