如何使用`catch_unwind`获取恐慌信息(即堆栈跟踪)?

问题描述 投票:0回答:1

如果使用

set_hook
,我们可以获得大量信息,尤其是堆栈跟踪 - 这非常有帮助。然而,对于
catch_unwind
,我只得到一个
Result
,其中几乎不包含任何有用的信息。因此,我想知道如何使用 Rust 的
catch_unwind
获取恐慌信息(尤其是堆栈跟踪)?

我处于一个“多线程”环境中,其中有许多线程同时运行,任何线程都可能出现恐慌。我想我应该将set_hook

catch_unwind
一起使用,并且还使用一些线程局部变量,但我不确定是否可行以及细节。
    

rust error-handling panic
1个回答
7
投票

Backtrace::capture()

(或在 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(); }


© www.soinside.com 2019 - 2024. All rights reserved.