rust - 如何使用 `catch_unwind` 获取 panic 信息(即堆栈跟踪)?

标签 rust error-handling panic

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

我处于一个多线程 环境中,其中有许多线程并发运行并且任何线程都可能出现 panic。我想我应该将set_hookcatch_unwind一起使用,并且还使用了一些线程局部变量,但我不确定是否可行以及细节。

最佳答案

您可以使用 backtrace 在 panic hook 中获取回溯。 crate ,但这对 catch_unwind 没有帮助因为堆栈已经从发生 panic 的地方展开。

你可以做的是走私 panic 钩子(Hook)的回溯到捕手中,方法是将它存储在 thread local 中。多变的。这应该是可靠的,因为 panic 是一个自动进程中止而 panic 是一个自动进程中止(所以你不能覆盖尚未被捕获的),并且 panic 不会传播跨线程边界(加入 panic thread 返回一个 Result<_, Box<dyn Any>> 并以 panic 作为错误)。

这是一个完整的例子:

use std::cell::RefCell;
use backtrace::Backtrace;

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::new();
        Backtrace.with(move |b| b.borrow_mut().replace(trace));
    }));
    
    g();
}

关于rust - 如何使用 `catch_unwind` 获取 panic 信息(即堆栈跟踪)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69593235/

相关文章:

angular - 当 rxjs throwError 重新抛出 http 错误响应时,自定义全局错误处理程序未命中

http - 去 http panic 服务

function - 如何使用任意类型作为函数参数?

rust - 为什么 Rust 需要在 "impl"关键字之后进行泛型类型声明?

rust - 尝试使用 serde_json 从 curl 解析 JSON 时类型不匹配

ruby-on-rails - 联系第 3 方 API 时的错误处理

linux - 无法从 Rust 应用程序中的 Serde 引起的回溯中跟踪错误

ruby-on-rails - Rails 完整错误页面未显示 View 错误

dictionary - 如何从并发映射写入中恢复?

戈朗 :how do I handle index out of range error?