blob: 36f6ae3da9388b3a1f262ddb942c9ab0325a3b37 [file] [log] [blame]
David Tolnay7db73692019-10-20 14:51:12 -04001use std::io::{self, Write};
David Tolnay4ad80202020-04-08 21:16:44 -07002use std::panic::{self, AssertUnwindSafe};
David Tolnay7db73692019-10-20 14:51:12 -04003use std::process;
4
5pub fn catch_unwind<F, R>(label: &'static str, foreign_call: F) -> R
6where
David Tolnay4ad80202020-04-08 21:16:44 -07007 F: FnOnce() -> R,
David Tolnay7db73692019-10-20 14:51:12 -04008{
David Tolnay4ad80202020-04-08 21:16:44 -07009 // Regarding the AssertUnwindSafe: we immediately abort on panic so it
10 // doesn't matter whether the types involved are unwind-safe. The UnwindSafe
11 // bound on catch_unwind is about ensuring nothing is in a broken state if
12 // your program plans to continue after the panic.
13 match panic::catch_unwind(AssertUnwindSafe(foreign_call)) {
David Tolnay7db73692019-10-20 14:51:12 -040014 Ok(ret) => ret,
15 Err(_) => abort(label),
16 }
17}
18
19#[cold]
20fn abort(label: &'static str) -> ! {
David Tolnay57a1eaa2020-04-08 21:20:25 -070021 let mut stderr = io::stderr();
22 let _ = writeln!(stderr, "Error: panic in ffi function {}, aborting.", label);
David Tolnay7db73692019-10-20 14:51:12 -040023 process::abort();
24}