gpt4 book ai didi

rust - 在 catch_unwind 期间将回溯转换为字符串

转载 作者:行者123 更新时间:2023-12-04 17:16:41 25 4
gpt4 key购买 nike

我正在用 Rust 编写一个跨平台(Linux/iOS/Android)库。如果我的库出现困惑,我希望应用程序继续正常工作而不是崩溃。为了做到这一点,我正在使用 catch_unwind ;它的结果包含 panic 信息,但没有包含足够的关于问题根源的信息,这里有一段代码解释了我在做什么:

fn calculate(json: &str) -> String {
unimplemented!()
}

#[no_mangle]
pub fn rust_calculation(json: &str) -> String {
let r = std::panic::catch_unwind(||{
// rust calculation
let calc: String = calculate(json).into();
calc
});
let r_str = match r {
Ok(v) => v,
Err(e) => {
let panic_information = match e.downcast::<String>() {
Ok(v) => *v,
_ => "Unknown Source of Error".to_owned()
};
panic_information
}
};
return r_str;
}

fn main() {
println!("{}", rust_calculation("test"));
}
Playground
如果发生错误,返回的消息是不够的,有时,它只包含消息

Unknown Source of Error


我想将回溯发送到调用源,以便它可以记录它,然后我们可以在之后调试 Rust 库。我怎样才能做到这一点?

最佳答案

some times it countains the message:

Unknown Source of Error



这可能是因为 e可能不仅是 String ,还有 &str (好吧,它基本上可以是任何类型,但这两种是最常见的,使用 panic_any() 时只能获取其他类型)。打电话时 panic!()catch_unwind() , 你只会得到一个 String如果您是 panic! ' 使用参数,否则, panic 消息是 &str (因为不需要分配 String )。

I want to send the backtrace to the calling source so that he can log it and then we can debug the rust library afterwards, how can I do that ?


每晚 Rust 的解决方案
在夜间 Rust 中,您可以通过 std::backtrace::Backtrace 在 panic 处理程序中生成回溯。 :
#![feature(backtrace)]
use lazy_static::lazy_static;
use std::sync::{Arc, Mutex};

// on panic, save the backtrace here (as string)
lazy_static! {
static ref BACKTRACE: Arc<Mutex<Option<String>>> = Arc::new(Mutex::new(None));
}

#[no_mangle]
pub fn rust_calculation(json: &str) -> String {
let r = std::panic::catch_unwind(||{
panic!("Panic");
});
let r_str = match r {
Ok(v) => v,
Err(e) => {
let panic_information = match e.downcast::<String>() {
Ok(v) => *v,
Err(e) => match e.downcast::<&str>() {
Ok(v) => v.to_string(),
_ => "Unknown Source of Error".to_owned()
}
};
format!("{}\nBacktrace:\n{}", panic_information, BACKTRACE.lock().unwrap().take().unwrap_or("<Backtrace not found>".to_string()))
}
};
return r_str;
}

fn panic_hook(_: &std::panic::PanicInfo) {
*BACKTRACE.lock().unwrap() = Some(std::backtrace::Backtrace::force_capture().to_string());
}

fn main() {
std::panic::set_hook(Box::new(panic_hook));
println!("{}", rust_calculation(""));
}
Playground link
输出:
Panic
Backtrace:
0: playground::panic_hook
at ./src/main.rs:32:39
1: core::ops::function::Fn::call
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/core/src/ops/function.rs:70:5
2: std::panicking::rust_panic_with_hook
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panicking.rs:626:17
3: std::panicking::begin_panic::{{closure}}
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panicking.rs:542:9
4: std::sys_common::backtrace::__rust_end_short_backtrace
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/sys_common/backtrace.rs:141:18
5: std::panicking::begin_panic
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panicking.rs:541:12
6: playground::rust_calculation::{{closure}}
at ./src/main.rs:13:9
7: std::panicking::try::do_call
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panicking.rs:401:40
8: __rust_try
9: std::panicking::try
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panicking.rs:365:19
10: std::panic::catch_unwind
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panic.rs:434:14
11: rust_calculation
at ./src/main.rs:12:13
12: playground::main
at ./src/main.rs:37:20
13: core::ops::function::FnOnce::call_once
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/core/src/ops/function.rs:227:5
14: std::sys_common::backtrace::__rust_begin_short_backtrace
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/sys_common/backtrace.rs:125:18
15: std::rt::lang_start::{{closure}}
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/rt.rs:63:18
16: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/core/src/ops/function.rs:259:13
17: std::panicking::try::do_call
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panicking.rs:401:40
18: std::panicking::try
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panicking.rs:365:19
19: std::panic::catch_unwind
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panic.rs:434:14
20: std::rt::lang_start_internal::{{closure}}
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/rt.rs:45:48
21: std::panicking::try::do_call
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panicking.rs:401:40
22: std::panicking::try
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panicking.rs:365:19
23: std::panic::catch_unwind
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/panic.rs:434:14
24: std::rt::lang_start_internal
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/rt.rs:45:20
25: std::rt::lang_start
at /rustc/2faabf579323f5252329264cc53ba9ff803429a3/library/std/src/rt.rs:62:5
26: main
27: __libc_start_main
28: _start
请注意,在调用 panic! 之后,此回溯包含一些额外的帧。这是由于 Rust 的内部 panic 处理代码。
具有依赖项的解决方案
如果你不是每晚使用 Rust,但愿意使用额外的依赖项,你可以用 backtrace crate 做同样的事情。 (感谢@BashirAbdelwahed 提醒我注意这一点):
use lazy_static::lazy_static;
use std::sync::{Arc, Mutex};

// on panic, save the backtrace here (as string)
lazy_static! {
static ref BACKTRACE: Arc<Mutex<Option<String>>> = Arc::new(Mutex::new(None));
}

#[no_mangle]
pub fn rust_calculation(json: &str) -> String {
let r = std::panic::catch_unwind(||{
panic!("Panic");
});
let r_str = match r {
Ok(v) => v,
Err(e) => {
let panic_information = match e.downcast::<String>() {
Ok(v) => *v,
Err(e) => match e.downcast::<&str>() {
Ok(v) => v.to_string(),
_ => "Unknown Source of Error".to_owned()
}
};
format!("{}\nBacktrace:\n{}", panic_information, BACKTRACE.lock().unwrap().take().unwrap_or("<Backtrace not found>".to_string()))
}
};
return r_str;
}

fn panic_hook(_: &std::panic::PanicInfo) {
*BACKTRACE.lock().unwrap() = Some(format!("{:?}", backtrace::Backtrace::new()));
}

fn main() {
std::panic::set_hook(Box::new(panic_hook));
println!("{}", rust_calculation(""));
}
Playground link
输出:
Panic
Backtrace:
0: playground::panic_hook
at src/main.rs:31:55
1: core::ops::function::Fn::call
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/ops/function.rs:70:5
2: std::panicking::rust_panic_with_hook
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:595:17
3: std::panicking::begin_panic::{{closure}}
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:520:9
4: std::sys_common::backtrace::__rust_end_short_backtrace
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/sys_common/backtrace.rs:141:18
5: std::panicking::begin_panic
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:519:12
6: playground::rust_calculation::{{closure}}
at src/main.rs:12:9
7: std::panicking::try::do_call
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:379:40
8: __rust_try
9: std::panicking::try
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:343:19
10: std::panic::catch_unwind
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panic.rs:431:14
11: rust_calculation
at src/main.rs:11:13
12: playground::main
at src/main.rs:36:20
13: core::ops::function::FnOnce::call_once
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/ops/function.rs:227:5
14: std::sys_common::backtrace::__rust_begin_short_backtrace
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/sys_common/backtrace.rs:125:18
15: std::rt::lang_start::{{closure}}
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/rt.rs:49:18
16: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/ops/function.rs:259:13
std::panicking::try::do_call
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:379:40
std::panicking::try
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:343:19
std::panic::catch_unwind
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panic.rs:431:14
std::rt::lang_start_internal
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/rt.rs:34:21
17: std::rt::lang_start
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/rt.rs:48:5
18: main
19: __libc_start_main
20: _start

关于rust - 在 catch_unwind 期间将回溯转换为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68556819/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com