From d28075221c730f5e34e2fd325a21d813d380bbb1 Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Sat, 6 Dec 2025 06:38:52 +0800 Subject: [PATCH] refactor(signal): migrate signal to handling async in unix and remove signal-hook dependency --- Cargo.lock | 1 - Changelog.md | 1 + crates/clash-verge-logging/src/lib.rs | 2 + crates/clash-verge-signal/Cargo.toml | 3 - crates/clash-verge-signal/src/lib.rs | 2 +- crates/clash-verge-signal/src/unix.rs | 77 ++++++++++++++++-------- crates/clash-verge-signal/src/windows.rs | 15 ++--- 7 files changed, 63 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 814590221..a5e8bd88f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1285,7 +1285,6 @@ version = "0.1.0" dependencies = [ "clash-verge-logging", "log", - "signal-hook 0.3.18", "tauri", "tokio", "windows-sys 0.61.2", diff --git a/Changelog.md b/Changelog.md index 50ee19f48..88b8877e7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -61,6 +61,7 @@ - 优化应用重启/退出时的资源清理性能, 大幅缩短执行时间 - 优化 WebSocket 连接机制 - 改进旧版 Service 需要重新安装检测流程 +- 优化 macOS 和 Linux 信号处理 diff --git a/crates/clash-verge-logging/src/lib.rs b/crates/clash-verge-logging/src/lib.rs index bb8672f53..a30c15ee7 100644 --- a/crates/clash-verge-logging/src/lib.rs +++ b/crates/clash-verge-logging/src/lib.rs @@ -18,6 +18,7 @@ pub enum Type { Config, Setup, System, + SystemSignal, Service, Hotkey, Window, @@ -42,6 +43,7 @@ impl fmt::Display for Type { Self::Config => write!(f, "[Config]"), Self::Setup => write!(f, "[Setup]"), Self::System => write!(f, "[System]"), + Self::SystemSignal => write!(f, "[SysSignal]"), Self::Service => write!(f, "[Service]"), Self::Hotkey => write!(f, "[Hotkey]"), Self::Window => write!(f, "[Window]"), diff --git a/crates/clash-verge-signal/Cargo.toml b/crates/clash-verge-signal/Cargo.toml index 2781509f2..6c59548c8 100644 --- a/crates/clash-verge-signal/Cargo.toml +++ b/crates/clash-verge-signal/Cargo.toml @@ -9,9 +9,6 @@ clash-verge-logging = { workspace = true } log = { workspace = true } tokio = { workspace = true } -[target.'cfg(unix)'.dependencies] -signal-hook = "0.3.18" - [target.'cfg(windows)'.dependencies] tauri = { workspace = true } windows-sys = { version = "0.61.2", features = [ diff --git a/crates/clash-verge-signal/src/lib.rs b/crates/clash-verge-signal/src/lib.rs index a7b7671bc..3d1d76b86 100644 --- a/crates/clash-verge-signal/src/lib.rs +++ b/crates/clash-verge-signal/src/lib.rs @@ -19,7 +19,7 @@ where Err(e) => { logging!( info, - Type::System, + Type::SystemSignal, "register shutdown signal failed, create tokio runtime error: {}", e ); diff --git a/crates/clash-verge-signal/src/unix.rs b/crates/clash-verge-signal/src/unix.rs index 9729c32b4..7991e8f74 100644 --- a/crates/clash-verge-signal/src/unix.rs +++ b/crates/clash-verge-signal/src/unix.rs @@ -1,10 +1,5 @@ -use signal_hook::{ - consts::{SIGHUP, SIGINT, SIGTERM}, - iterator::Signals, - low_level, -}; - -use clash_verge_logging::{Type, logging, logging_error}; +use clash_verge_logging::{Type, logging}; +use tokio::signal::unix::{SignalKind, signal}; use crate::RUNTIME; @@ -15,39 +10,69 @@ where { if let Some(Some(rt)) = RUNTIME.get() { rt.spawn(async move { - let signals = [SIGTERM, SIGINT, SIGHUP]; - - let mut sigs = match Signals::new(signals) { + let mut sigterm = match signal(SignalKind::terminate()) { Ok(s) => s, Err(e) => { - logging!(error, Type::System, "注册信号处理器失败: {}", e); + logging!( + error, + Type::SystemSignal, + "Failed to register SIGTERM: {}", + e + ); + return; + } + }; + let mut sigint = match signal(SignalKind::interrupt()) { + Ok(s) => s, + Err(e) => { + logging!( + error, + Type::SystemSignal, + "Failed to register SIGINT: {}", + e + ); + return; + } + }; + let mut sighup = match signal(SignalKind::hangup()) { + Ok(s) => s, + Err(e) => { + logging!( + error, + Type::SystemSignal, + "Failed to register SIGHUP: {}", + e + ); return; } }; - for signal in &mut sigs { - let signal_to_str = |signal| match signal { - SIGTERM => "SIGTERM", - SIGINT => "SIGINT", - SIGHUP => "SIGHUP", - _ => "UNKNOWN", - }; + loop { + let signal_name; + tokio::select! { + _ = sigterm.recv() => { + signal_name = "SIGTERM"; + } + _ = sigint.recv() => { + signal_name = "SIGINT"; + } + _ = sighup.recv() => { + signal_name = "SIGHUP"; + } + else => { + break; + } + } - logging!(info, Type::System, "捕获到信号 {}", signal_to_str(signal)); + logging!(info, Type::SystemSignal, "Caught signal {}", signal_name); f().await; - - logging_error!( - Type::System, - "信号 {:?} 默认处理失败", - low_level::emulate_default_handler(signal) - ); } }); } else { logging!( error, - Type::System, + Type::SystemSignal, "register shutdown signal failed, RUNTIME is not available" ); } diff --git a/crates/clash-verge-signal/src/windows.rs b/crates/clash-verge-signal/src/windows.rs index 860208a28..ba4c8b767 100644 --- a/crates/clash-verge-signal/src/windows.rs +++ b/crates/clash-verge-signal/src/windows.rs @@ -33,7 +33,7 @@ unsafe impl Sync for ShutdownState {} impl Drop for ShutdownState { fn drop(&mut self) { // this log not be printed, I don't know why. - logging!(info, Type::System, "正在销毁系统关闭监听窗口"); + logging!(info, Type::SystemSignal, "正在销毁系统关闭监听窗口"); unsafe { DestroyWindow(self.hwnd); } @@ -52,7 +52,7 @@ unsafe extern "system" fn shutdown_proc( WM_QUERYENDSESSION => { logging!( info, - Type::System, + Type::SystemSignal, "System is shutting down or user is logging off." ); } @@ -60,21 +60,21 @@ unsafe extern "system" fn shutdown_proc( if let Some(handler) = SHUTDOWN_HANDLER.get() { if let Some(Some(rt)) = RUNTIME.get() { rt.block_on(async { - logging!(info, Type::System, "Session ended, system shutting down."); + logging!(info, Type::SystemSignal, "Session ended, system shutting down."); handler().await; - logging!(info, Type::System, "resolved reset finished"); + logging!(info, Type::SystemSignal, "resolved reset finished"); }); } else { logging!( error, - Type::System, + Type::SystemSignal, "handle shutdown signal failed, RUNTIME is not available" ); } } else { logging!( error, - Type::System, + Type::SystemSignal, "WM_ENDSESSION received but no shutdown handler is registered" ); } @@ -105,6 +105,7 @@ fn get_instance_handle() -> windows_sys::Win32::Foundation::HMODULE { unsafe { &__ImageBase as *const _ as _ } } +//? 我们有机会采用类似 tokio 信号,不阻塞信号线程吗? pub fn register(app_handle: &AppHandle, f: F) where F: Fn() -> Fut + Send + Sync + 'static, @@ -153,7 +154,7 @@ where std::ptr::null_mut(), ); if hwnd.is_null() { - logging!(error, Type::System, "failed to create shutdown window"); + logging!(error, Type::SystemSignal, "failed to create shutdown window"); } else { app_handle.manage(ShutdownState { hwnd }); }