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) {
|
extern "C" fn exception_cleanup(ptr: *mut libc::c_void) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::drop_in_place(ptr as *mut Exception);
|
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 {
|
unsafe {
|
||||||
let _: Box<Exception> = Box::from_raw(exception as *mut Exception);
|
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;
|
mod dwarf;
|
||||||
|
|
||||||
// Entry point for catching an exception, implemented using the `try` intrinsic
|
// 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]) {
|
unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) {
|
||||||
if (*e)[0] != 0 {
|
if (*e)[0] != 0 {
|
||||||
cleanup(*e);
|
cleanup(*e);
|
||||||
|
super::__rust_drop_panic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[unwind(allowed)]
|
#[unwind(allowed)]
|
||||||
|
@ -55,6 +55,14 @@ extern "C" {
|
|||||||
fn __rust_start_panic(payload: usize) -> u32;
|
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)]
|
#[derive(Copy, Clone)]
|
||||||
enum Hook {
|
enum Hook {
|
||||||
Default,
|
Default,
|
||||||
|
@ -57,21 +57,4 @@ extern "C" {
|
|||||||
throw;
|
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" {
|
extern "C" {
|
||||||
fn throw_cxx_exception();
|
fn throw_cxx_exception();
|
||||||
|
|
||||||
fn swallow_exception(cb: extern "C" fn());
|
|
||||||
|
|
||||||
#[unwind(allowed)]
|
#[unwind(allowed)]
|
||||||
fn cxx_catch_callback(cb: extern "C" fn(), ok: *mut bool);
|
fn cxx_catch_callback(cb: extern "C" fn(), ok: *mut bool);
|
||||||
}
|
}
|
||||||
@ -61,34 +59,7 @@ fn throw_rust_panic() {
|
|||||||
assert!(cxx_ok);
|
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() {
|
fn main() {
|
||||||
unsafe { throw_cxx_exception() };
|
unsafe { throw_cxx_exception() };
|
||||||
throw_rust_panic();
|
throw_rust_panic();
|
||||||
check_exception_drop();
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user