Rust捕獲全局panic并記錄進程退出日志的方法
本文提供了捕獲全局panic并記錄進程退出日志的方法。
1. 使用 panic::set_hook 注冊異常處理
use human_panic::setup_panic;
use log::error;
use std::{boxed::Box, panic};
fn hook(panic_info: &panic::PanicInfo) {
if cfg!(debug_assertions) {
let err_message = format!("panic occurred {:?}", panic_info);
error!("{}", err_message);
} else {
let err_message = match panic_info.payload().downcast_ref::<&str>() {
Option::Some(&str) => {
let err_message = format!(
"panic info: {:?}, occurred in {:?}",
str,
panic_info.location()
);
err_message
}
Option::None => {
let err_message =
format!("panic occurred in {:?}", panic_info.location());
err_message
}
};
error!("{}", err_message);
}
}
/// 注冊異常處理函數(shù)
/// 在panic發(fā)出后,在panic運行時之前,觸發(fā)鉤子函數(shù)去處理這個panic信息。
/// panic信息被保存在PanicInfo結(jié)構(gòu)體中。
pub fn register_panic_hook() {
panic::set_hook(Box::new(|panic_info| {
hook(panic_info);
}));
// setup_panic!();
}2. panic 觸發(fā)異常
use core_utils::panic::register_panic_hook;
use core_utils::panic::register_panic_hook;
use env_logger;
use log::LevelFilter;
use std::thread;
use std::time::Duration;
#[test]
fn test_panic_set_hook() {
let _ = env_logger::builder()
.is_test(true)
.filter(None, LevelFilter::Debug)
.try_init();
register_panic_hook();
thread::spawn(|| {
panic!("child thread panic");
});
thread::sleep(Duration::from_millis(100));
}日志如下
debug模式
[2024-04-20T05:32:30Z ERROR core_utils::panic] panic occurred PanicInfo { payload: Any { .. }, message: Some(child thread panic), location: Location { file: "core_utils/tests/test_panic.rs", line: 16, col: 9 }, can_unwind: true, force_no_backtrace: false }release模式
[2024-04-20T05:41:06Z ERROR core_utils::panic] panic info: "child thread panic", occurred in Some(Location { file: "core_utils/tests/test_panic.rs", line: 17, col: 9 })3. unwrap 觸發(fā)異常
#[test]
fn test_panic_unwrap() {
let _ = env_logger::builder()
.is_test(true)
.filter(None, LevelFilter::Debug)
.try_init();
register_panic_hook();
thread::spawn(|| {
let _ = "abc".parse::<i32>().unwrap();
});
thread::sleep(Duration::from_millis(100));
}日志如下
debug模式
[2024-04-20T05:38:22Z ERROR core_utils::panic] panic occurred PanicInfo { payload: Any { .. }, message: Some(called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }), location: Location { file: "core_utils/tests/test_panic.rs", line: 33, col: 38 }, can_unwind: true, force_no_backtrace: false }release模式
注意:unwrap觸發(fā)的異常會導致 panic_info.payload().downcast_ref::<&str>()返回結(jié)果為 None
[2024-04-20T05:42:34Z ERROR core_utils::panic] panic occurred in Some(Location { file: "core_utils/tests/test_panic.rs", line: 33, col: 38 })4. 使用 human_panic
human_panic只能在非debug模式且環(huán)境變量RUST_BACKTRACE未設(shè)置的情況下才會生效。
注冊 hook
use human_panic::setup_panic;
pub fn register_panic_hook() {
setup_panic!();
}模擬release環(huán)境異常
use core_utils::panic::register_panic_hook;
use env_logger;
use human_panic::setup_panic;
use log::error;
use std::thread;
use std::time::Duration;
fn main() {
env_logger::init();
register_panic_hook();
thread::spawn(|| {
panic!("error");
// let _ = "abc".parse::<i32>().unwrap();
});
thread::sleep(Duration::from_secs(1));
}cargo run --bin human_panic --release
panic發(fā)生時會在在臨時文件夾下面創(chuàng)建一個報告文件
Well, this is embarrassing. core_utils had a problem and crashed. To help us diagnose the problem you can send us a crash report. We have generated a report file at "/var/folders/gx/hn6l2rd56cx0lcwnkblxqvmr0000gn/T/report-93547ab5-9341-4212-a9af-6d2f17d6311d.toml". Submit an issue or email with the subject of "core_utils Crash Report" and include the report as an attachment. We take privacy seriously, and do not perform any automated error collection. In order to improve the software, we rely on people to submit reports. Thank you kindly!
報告內(nèi)容如下
"name" = "core_utils"
"operating_system" = "Mac OS 14.1.1 [64-bit]"
"crate_version" = "0.1.0"
"explanation" = """
Panic occurred in file 'core_utils/src/bin/human_panic.rs' at line 14
"""
"cause" = "error"
"method" = "Panic"
"backtrace" = """
0: 0x105b840a5 - core::panicking::panic_fmt::h2aac8cf45f7ae617
1: 0x1059fd7c6 - std::sys_common::backtrace::__rust_begin_short_backtrace::h4bae865db206eae3
2: 0x1059fe2fd - core::ops::function::FnOnce::call_once{{vtable.shim}}::ha8d441119e8b7a5a
3: 0x105b5a819 - std::sys::pal::unix::thread::Thread::new::thread_start::h679ffa03f8a73496
4: 0x7ff801993202 - __pthread_start"""到此這篇關(guān)于Rust捕獲全局panic并記錄進程退出日志的文章就介紹到這了,更多相關(guān)rust 捕獲全局panic內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
rust使用Atomic創(chuàng)建全局變量和使用操作方法
從 Rust1.34 版本后,就正式支持原子類型,原子指的是一系列不可被 CPU 上下文交換的機器指令,這些指令組合在一起就形成了原子操作,這篇文章主要介紹了rust使用Atomic創(chuàng)建全局變量和使用,需要的朋友可以參考下2024-05-05
Rust字符串深度解析String與str的問題小結(jié)
在Rust編程語言中,字符串處理是一個核心概念,但與其他語言不同的是,Rust提供了兩種主要的字符串類型:String和&str,本文介紹Rust字符串深度解析String與str的問題,感興趣的朋友跟隨小編一起看看吧2026-03-03
詳解Rust調(diào)用tree-sitter支持自定義語言解析
使用Rust語言結(jié)合tree-sitter庫解析自定義語言需要定義語法、生成C解析器,并在Rust項目中集成,具體步驟包括創(chuàng)建grammar.js定義語法,使用tree-sitter-cli工具生成C解析器,以及在Rust項目中編寫代碼調(diào)用解析器,這一過程涉及到對tree-sitter的深入理解和Rust語言的應用技巧2024-09-09

