在Rust中从hook中的panic中检索回溯?

gojuced7  于 2023-10-20  发布在  其他
关注(0)|答案(3)|浏览(158)

我的应用程序需要通过标准输出将日志以JSON格式发送到fluentd。
当我试图处理 panics 并将&std::panic::PanicInfo安排为std::panic::set_hook的JSON时,我无法找到从&PanicInfo检索 backtrace 的方法。
有没有一种方法可以从自定义钩子中的panic中检索回溯?

w7t8yxp5

w7t8yxp51#

PanicInfo不包含回溯,但您可以在panic hook中自己捕获它。
set_hook文档:
注册一个自定义的紧急挂接,替换以前注册的任何挂接。
当线程发生异常时,在调用异常运行时之前,调用异常钩子。因此,钩子将在中止和展开运行时运行。默认钩子打印一条消息到标准错误,并在请求时生成一个回溯,但是这个行为可以用set_hooktake_hook函数来定制。
由于panic hook会在解卷之前运行***,所以你可以使用@hellow已经提到的backtrace crate在panic hook中自己捕获回溯:

panic::set_hook(Box::new(|panic_info| {
    let backtrace = Backtrace::new();
    //  Do something with backtrace and panic_info.
}));
oo7oh9g9

oo7oh9g92#

您可以使用backtrace crate来生成当前堆栈的回溯。
这与rust在内部使用RUST_BACKTRACE=1时发生panic时使用的crate完全相同。
最简单的例子(取自文档)就是调用backtrace::Backtrace

use backtrace::Backtrace;

fn main() {
    println!("{:?}", Backtrace::new());
}

我将返回(在我的示例中)

stack backtrace:
   0: playground::main::h990b23e2761eee55 (0x564800753fb1)
             at src/main.rs:4
   1: std::rt::lang_start::{{closure}}::hd025ca578a744b4f (0x564800753d3f)
             at /rustc/9fda7c2237db910e41d6a712e9a2139b352e558b/src/libstd/rt.rs:74
   2: std::rt::lang_start_internal::{{closure}}::hdfc28107b5be47c9 (0x564800789f92)
             at src/libstd/rt.rs:59
      std::panicking::try::do_call::h69790245ac2d03fe
             at src/libstd/panicking.rs:310
   3: __rust_maybe_catch_panic (0x564800797409)
             at src/libpanic_unwind/lib.rs:102
   4: std::panicking::try::h9c1cbc5599e1efbf (0x56480078a963)
             at src/libstd/panicking.rs:289
      std::panic::catch_unwind::h0562757d03ff60b3
             at src/libstd/panic.rs:398
      std::rt::lang_start_internal::h540c897fe52ba9c5
             at src/libstd/rt.rs:58
   5: std::rt::lang_start::h78189d3d761bfa86 (0x564800753d18)
             at /rustc/9fda7c2237db910e41d6a712e9a2139b352e558b/src/libstd/rt.rs:74
   6: main (0x5648007540b9)
   7: __libc_start_main (0x7fdab1a23b96)
   8: _start (0x564800753be9)
   9: <unknown> (0x0)
xxls0lw8

xxls0lw83#

从Rust 1.65开始,你可以在稳定通道上使用std::backtrace::Backtrace,不需要外部crate:

std::panic::set_hook(Box::new(|panic_info| {
    let backtrace = std::backtrace::Backtrace::capture();
    eprintln!("My backtrace: {:#?}", backtrace);
}));

相关问题