blob: abb7b921aa8135ab6b57c8f98abef81b5e857c1c [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) -> ! {
21 let mut stdout = io::stdout();
22 let _ = writeln!(stdout, "Error: panic in ffi function {}, aborting.", label);
23 process::abort();
24}