Abort if C++ tries to swallow a Rust panic
This commit is contained in:
parent
757ed07f37
commit
3a025760be
@ -80,6 +80,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
|
||||
extern "C" fn exception_cleanup(ptr: *mut libc::c_void) {
|
||||
unsafe {
|
||||
ptr::drop_in_place(ptr as *mut Exception);
|
||||
super::__rust_drop_panic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
|
||||
) {
|
||||
unsafe {
|
||||
let _: Box<Exception> = Box::from_raw(exception as *mut Exception);
|
||||
super::__rust_drop_panic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,12 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
/// Handler in libstd called when a panic object is dropped outside of
|
||||
/// `catch_unwind`.
|
||||
fn __rust_drop_panic() -> !;
|
||||
}
|
||||
|
||||
mod dwarf;
|
||||
|
||||
// Entry point for catching an exception, implemented using the `try` intrinsic
|
||||
|
@ -229,6 +229,7 @@ macro_rules! define_cleanup {
|
||||
unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) {
|
||||
if (*e)[0] != 0 {
|
||||
cleanup(*e);
|
||||
super::__rust_drop_panic();
|
||||
}
|
||||
}
|
||||
#[unwind(allowed)]
|
||||
|
@ -55,6 +55,14 @@ extern "C" {
|
||||
fn __rust_start_panic(payload: usize) -> u32;
|
||||
}
|
||||
|
||||
/// This function is called by the panic runtime if FFI code catches a Rust
|
||||
/// panic but doesn't rethrow it. We don't support this case since it messes
|
||||
/// with our panic count.
|
||||
#[rustc_std_internal_symbol]
|
||||
extern "C" fn __rust_drop_panic() -> ! {
|
||||
rtabort!("Rust panics must be rethrown");
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum Hook {
|
||||
Default,
|
||||
|
@ -57,21 +57,4 @@ extern "C" {
|
||||
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 (...)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,6 @@ impl<'a> Drop for DropCheck<'a> {
|
||||
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);
|
||||
}
|
||||
@ -61,34 +59,7 @@ fn throw_rust_panic() {
|
||||
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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user