如果使用
set_hook
,我们可以获得大量信息,尤其是堆栈跟踪 - 这非常有帮助。然而,对于 catch_unwind
,我只得到一个 Result
,其中几乎不包含任何有用的信息。因此,我想知道如何使用 Rust 的catch_unwind
获取恐慌信息(尤其是堆栈跟踪)?
我处于一个“多线程”环境中,其中有许多线程同时运行,任何线程都可能出现恐慌。我想我应该将set_hook
与
catch_unwind
一起使用,并且还使用一些线程局部变量,但我不确定是否可行以及细节。(或在 1.65 之前通过backtrace 板条箱)在恐慌钩子中获得回溯,但这对
catch_unwind
没有帮助,因为堆栈已经从恐慌发生的地方。您可以做的是通过将其存储在线程本地
变量中,将恐慌钩子的回溯信息走私到捕手中。这应该是可靠的,因为恐慌时的恐慌是一种自动进程中止(因此您无法覆盖尚未捕获的进程),并且恐慌不会跨线程边界传播(加入恐慌线程会返回一个Result<_, Box<dyn Any>>
) 将恐慌视为错误)。
这是一个完整的示例:
use std::backtrace::Backtrace;
use std::cell::RefCell;
thread_local! {
static BACKTRACE: RefCell<Option<Backtrace>> = RefCell::new(None);
}
fn f() {
panic!("xyz");
}
fn g() {
if let Err(err) = std::panic::catch_unwind(f) {
let b = BACKTRACE.with(|b| b.borrow_mut().take()).unwrap();
println!("at panic:\n{}", b);
}
}
fn main() {
std::panic::set_hook(Box::new(|_| {
let trace = Backtrace::capture();
BACKTRACE.with(move |b| b.borrow_mut().replace(trace));
}));
g();
}