Open dgrunwald opened 8 years ago
Yeah, sadly, there's no obvious way to fix this unless new APIs have been added to Rust since I last looked. But thank you for the report.
In general, abort_on_panic!
is mostly used inside Rust routines called from C, or at the very top of a Rust thread.
I'm now using something like this:
struct AbortOnDrop<'a>(pub &'a str);
impl <'a> Drop for AbortOnDrop<'a> {
fn drop(&mut self) {
use std::io::Write;
let _ = writeln!(&mut io::stderr(), "Cannot unwind out of {}", self.0);
unsafe { libc::abort() }
}
}
pub fn abort_on_panic<F, T>(location: &str, f: F) -> T
where F: FnOnce() -> T
{
let guard = AbortOnDrop(location);
let ret = f();
mem::forget(guard);
ret
}
But that's a pretty major API change. Using a closure seems to be the only way though, in all other cases the user code could bypass the mem::forget
call.
Interesting. I need to think about that design for a bit. I don't really want to change the API, but maybe I could provide both or find another solution here.
In light of the new support for panic = 'abort'
in Rust, I'm not sure what the best way to handle more complicated use cases of this crate might be. I'm tempted to leave it as a very simple crate with a limited API for people who need to abort even when the global policy is panic = 'abort'
. But I'm open to other suggestions.
If anybody would like to discuss this topic, please comment on this issue.
This crate is not entirely obsolete. I have a wrapper around a C library and, because the goal is to provide a safe API, I do not want to require my users deal with the UB of panics crossing the FFI boundary. Also, as a library, I don't have control over panic = 'abort'
. This means that I need to do something that is both relatively sane and well-defined if the callback panics - abort.
The solution to this issue is to create a function modeled after catch_unwind
but doesn't have the unfortunate exception-safe requirement. This serves as a drop-in replacement for catch_unwind
but removes the exception-safe requirement by aborting.
pub fn abort_unwind<F: FnOnce() -> R, R>(f: F) -> R {
struct Guard;
impl Drop for Guard {
fn drop(&mut self) {
if std::thread::panicking() {
std::process::abort();
}
}
}
let _guard = Guard;
f()
}