I run some code in a separate thread:
fn f1() -> Result<(), String> { Err("err1".to_string()) }
fn f2() -> Result<(), String> { Err("err2".to_string()) }
::std::thread::spawn(move || {
f1().expect("f1 failed");
f2().expect("f2 failed");
});
also I use log crate for logging.
As result I want panic!
to call error!
instead of print!
.
I found the panic hook, but I do not like unwrap
in such code:
panic::set_hook(Box::new(|panic_info| {
error!("panic occured: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap());
}));
and I am worried about:
This will commonly, but not always, be a
&'static str
orString
but would not downcast
always succeeded?
This will commonly, but not always, be a
&'static str
orString
This means that a developer (of one the libraries you use) could potentially use another type. In this case, the call to downcast_ref
would fail.
My advice is to handle the cases you know about and add a catch-all case with a default message.
Also you should also consider printing the location, as it is incredibly useful even in the absence of message.
All told:
use std::panic;
use std::ops::Deref;
panic::set_hook(Box::new(|panic_info| {
let (filename, line) =
panic_info.location().map(|loc| (loc.file(), loc.line()))
.unwrap_or(("<unknown>", 0));
let cause = panic_info.payload().downcast_ref::<String>().map(String::deref);
let cause = cause.unwrap_or_else(||
panic_info.payload().downcast_ref::<&str>().map(|s| *s)
.unwrap_or("<cause unknown>")
);
error!("A panic occurred at {}:{}: {}", filename, line, cause);
}));
Let's unwrap it:
payload
is a String
, and if so dereference it,&str
, and if not provide a default,If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With