32

I'm using panic::catch_unwind to catch a panic:

use std::panic;

fn main() {
    let result = panic::catch_unwind(|| {
        panic!("test panic");
    });

    match result {
        Ok(res) => res,
        Err(_) => println!("caught panic!"),
    }
}

(Playground)

This seems to work just fine, but I am still getting the output of the panic to stdout. I'd like this to only print out:

caught panic!

Instead of

thread '<main>' panicked at 'test panic', <anon>:6
note: Run with `RUST_BACKTRACE=1` for a backtrace.
caught panic!
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Matt
  • 4,029
  • 3
  • 20
  • 37

3 Answers3

34

You need to register a panic hook with std::panic::set_hook that does nothing. You can then catch it with std::panic::catch_unwind:

use std::panic;

fn main() {
    panic::set_hook(Box::new(|_info| {
        // do nothing
    }));

    let result = panic::catch_unwind(|| {
        panic!("test panic");
    });

    match result {
        Ok(res) => res,
        Err(_) => println!("caught panic!"),
    }
}

As Matthieu M. notes, you can get the current hook with std::panic::take_hook in order to restore it afterwards, if you need to.

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 4
    Note: one can use `take_handler` first to be able to restore the original handler after recovery. – Matthieu M. Feb 23 '16 at 08:03
  • 3
    You generally want to install a panic handler once in the beginning of main, before starting any threads and never uninstall it. Instead the panic handler should look at a thread-local variable to decide if it should call the next handler in the chain or if it should swallow the panic silently. – CodesInChaos Jul 24 '18 at 10:29
  • @CodesInChaos Hi, I wonder whether it is thread safe? Related: https://stackoverflow.com/questions/69593235/how-to-get-panic-information-especially-stack-trace-with-rusts-catch-unwind?noredirect=1#comment123009419_69593235 Thanks! – ch271828n Oct 16 '21 at 07:03
8

Use following catch_unwind_silent instead of regular catch_unwind to achieve silence for expected exceptions:

use std::panic;

fn catch_unwind_silent<F: FnOnce() -> R + panic::UnwindSafe, R>(f: F) -> std::thread::Result<R> {
    let prev_hook = panic::take_hook();
    panic::set_hook(Box::new(|_| {}));
    let result = panic::catch_unwind(f);
    panic::set_hook(prev_hook);
    result
}
k06a
  • 17,755
  • 10
  • 70
  • 110
  • But how can one read the panic message from the result? I checked all its fields but could not find it. Thanks! – mirind4 Jan 14 '22 at 19:07
2

You can use std::panic::set_hook to suppress the output. Note however that the hook is process-global and it will suppress reporting on all panics that may occur within the program.

As already plugged in my answer to a similar question, I've written a crate that provides a way to suppress the hook with composable filters, including one that works on a per-thread basis.

mzabaluev
  • 532
  • 5
  • 13