diff --git a/src-tauri/src/utils/error.rs b/src-tauri/src/utils/error.rs new file mode 100644 index 00000000..d661b609 --- /dev/null +++ b/src-tauri/src/utils/error.rs @@ -0,0 +1,40 @@ +use crate::log_err; +use anyhow; +use std::{ + backtrace::{Backtrace, BacktraceStatus}, + thread, +}; + +pub fn redirect_panic_to_log() { + std::panic::set_hook(Box::new(move |panic_info| { + let thread = thread::current(); + let thread_name = thread.name().unwrap_or(""); + let payload = panic_info.payload(); + + let payload = if let Some(s) = payload.downcast_ref::<&str>() { + &**s + } else if let Some(s) = payload.downcast_ref::() { + s + } else { + &format!("{:?}", payload) + }; + + let location = panic_info + .location() + .map(|l| l.to_string()) + .unwrap_or("unknown location".to_string()); + + let backtrace = Backtrace::capture(); + let backtrace = if backtrace.status() == BacktraceStatus::Captured { + &format!("stack backtrace:\n{}", backtrace) + } else { + "note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace" + }; + + let err: Result<(), anyhow::Error> = Err(anyhow::anyhow!(format!( + "thread '{}' panicked at {}:\n{}\n{}", + thread_name, location, payload, backtrace + ))); + log_err!(err); + })); +} diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/src/utils/mod.rs index 28eacc3b..b5ee04e7 100644 --- a/src-tauri/src/utils/mod.rs +++ b/src-tauri/src/utils/mod.rs @@ -1,4 +1,5 @@ pub mod dirs; +pub mod error; pub mod help; pub mod init; pub mod resolve; diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs index 079004e6..54081444 100644 --- a/src-tauri/src/utils/resolve.rs +++ b/src-tauri/src/utils/resolve.rs @@ -1,5 +1,6 @@ use crate::cmds::import_profile; use crate::config::IVerge; +use crate::utils::error; use crate::{config::Config, core::*, utils::init, utils::server}; use crate::{log_err, trace_err}; use anyhow::Result; @@ -32,6 +33,7 @@ pub fn find_unused_port() -> Result { /// handle something when start app pub async fn resolve_setup(app: &mut App) { + error::redirect_panic_to_log(); #[cfg(target_os = "macos")] app.set_activation_policy(tauri::ActivationPolicy::Accessory); let version = app.package_info().version.to_string();