From 18c5c3fd34ceb8a1631f7766b69e407cf92e1a09 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Fri, 15 May 2026 21:54:11 +0800 Subject: Add panic catch for program execution --- mingling_core/src/program.rs | 50 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'mingling_core/src/program.rs') diff --git a/mingling_core/src/program.rs b/mingling_core/src/program.rs index f2809f7..e7e9ec0 100644 --- a/mingling_core/src/program.rs +++ b/mingling_core/src/program.rs @@ -1,3 +1,5 @@ +use crate::error::ProgramPanic; + #[cfg(feature = "comp")] use crate::{ShellContext, Suggest}; @@ -21,6 +23,8 @@ use std::{ #[cfg(feature = "async")] use std::pin::Pin; +#[doc(hidden)] +pub mod error; #[doc(hidden)] pub mod exec; #[doc(hidden)] @@ -175,7 +179,7 @@ impl Program where C: ProgramCollect, { - async fn exec_wrapper(self, f: F) -> Fut::Output + async fn exec_wrapper(self, f: F) -> Result where C: 'static + Send + Sync, F: FnOnce(&'static Program) -> Fut + Send + Sync, @@ -189,7 +193,16 @@ where .unwrap() .downcast_ref::>() .unwrap(); - f(program).await + match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(program))) { + Ok(fut) => Ok(fut.await), + Err(panic_info) => { + let panic_payload = ProgramPanic { + payload: panic_info, + }; + program.run_hook_exec_panic(&panic_payload); + Err(panic_payload) + } + } } /// Run the command line program @@ -198,8 +211,13 @@ where C: 'static + Send + Sync, { self.args = self.args.iter().skip(1).cloned().collect(); - self.exec_wrapper(|p| async { crate::exec::exec(p).await.map_err(|e| e.into()) }) + match self + .exec_wrapper(|p| async { crate::exec::exec(p).await.map_err(|e| e.into()) }) .await + { + Ok(r) => r, + Err(e) => Err(ProgramExecuteError::Panic(e)), + } } /// Run the command line program @@ -223,6 +241,10 @@ where eprintln!("{}", e); return 1; } + ProgramExecuteError::Panic(unwinded_error) => { + eprintln!("{}", unwinded_error); + return 1; + } }, }; @@ -259,7 +281,7 @@ impl Program where C: ProgramCollect, { - fn exec_wrapper(self, f: F) -> R + fn exec_wrapper(self, f: F) -> Result where C: 'static + Send + Sync, F: FnOnce(&'static Program) -> R + Send + Sync, @@ -272,7 +294,16 @@ where .unwrap() .downcast_ref::>() .unwrap(); - f(program) + match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(program))) { + Ok(result) => Ok(result), + Err(panic_info) => { + let panic_payload = ProgramPanic { + payload: panic_info, + }; + program.run_hook_exec_panic(&panic_payload); + Err(panic_payload) + } + } } /// Run the command line program @@ -281,7 +312,10 @@ where C: 'static + Send + Sync, { self.args = self.args.iter().skip(1).cloned().collect(); - self.exec_wrapper(|p| crate::exec::exec(p).map_err(|e| e.into())) + match self.exec_wrapper(|p| crate::exec::exec(p).map_err(|e| e.into())) { + Ok(r) => r, + Err(e) => Err(ProgramExecuteError::Panic(e)), + } } /// Run the command line program @@ -305,6 +339,10 @@ where eprintln!("{}", e); return 1; } + ProgramExecuteError::Panic(unwinded_error) => { + eprintln!("{}", unwinded_error); + return 1; + } }, }; -- cgit