| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 1 | use std::io::{self, Write}; |
| David Tolnay | 4ad8020 | 2020-04-08 21:16:44 -0700 | [diff] [blame] | 2 | use std::panic::{self, AssertUnwindSafe}; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 3 | use std::process; |
| 4 | |
| 5 | pub fn catch_unwind<F, R>(label: &'static str, foreign_call: F) -> R |
| 6 | where |
| David Tolnay | 4ad8020 | 2020-04-08 21:16:44 -0700 | [diff] [blame] | 7 | F: FnOnce() -> R, |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 8 | { |
| David Tolnay | 4ad8020 | 2020-04-08 21:16:44 -0700 | [diff] [blame] | 9 | // 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 Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 14 | Ok(ret) => ret, |
| 15 | Err(_) => abort(label), |
| 16 | } |
| 17 | } |
| 18 | |
| 19 | #[cold] |
| 20 | fn abort(label: &'static str) -> ! { |
| David Tolnay | 57a1eaa | 2020-04-08 21:20:25 -0700 | [diff] [blame^] | 21 | let mut stderr = io::stderr(); |
| 22 | let _ = writeln!(stderr, "Error: panic in ffi function {}, aborting.", label); |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 23 | process::abort(); |
| 24 | } |