Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::result::Result panic to log

Tags:

rust

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 or String

but would not downcast always succeeded?

like image 715
user1244932 Avatar asked Oct 16 '25 22:10

user1244932


1 Answers

This will commonly, but not always, be a &'static str or String

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:

  • first we fetch the filename and line from the location, providing defaults in case they are unknown,
  • then we check whether the payload is a String, and if so dereference it,
  • then, if not, we check if it is a &str, and if not provide a default,
  • finally, we print all the accumulated information.
like image 161
Matthieu M. Avatar answered Oct 18 '25 14:10

Matthieu M.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!