mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-28 07:14:40 +08:00
feat(signal): add clash-verge-signal crate and integrate signal handling (#5500)
* feat(signal): add clash-verge-signal crate and integrate signal handling * fix: clippy error on type complexity
This commit is contained in:
14
Cargo.lock
generated
14
Cargo.lock
generated
@@ -1117,6 +1117,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"clash-verge-draft",
|
||||
"clash-verge-logging",
|
||||
"clash-verge-signal",
|
||||
"clash_verge_logger",
|
||||
"clash_verge_service_ipc",
|
||||
"compact_str",
|
||||
@@ -1147,7 +1148,6 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml_ng",
|
||||
"signal-hook 0.3.18",
|
||||
"smartstring",
|
||||
"sys-locale",
|
||||
"sysinfo",
|
||||
@@ -1172,7 +1172,6 @@ dependencies = [
|
||||
"tokio-stream",
|
||||
"warp",
|
||||
"winapi",
|
||||
"windows-sys 0.61.2",
|
||||
"winreg 0.55.0",
|
||||
"zip 6.0.0",
|
||||
]
|
||||
@@ -1197,6 +1196,17 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clash-verge-signal"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clash-verge-logging",
|
||||
"log",
|
||||
"signal-hook 0.3.18",
|
||||
"tauri",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clash_verge_logger"
|
||||
version = "0.2.1"
|
||||
|
||||
@@ -3,6 +3,7 @@ members = [
|
||||
"src-tauri",
|
||||
"crates/clash-verge-draft",
|
||||
"crates/clash-verge-logging",
|
||||
"crates/clash-verge-signal",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
@@ -42,6 +43,8 @@ strip = false
|
||||
[workspace.dependencies]
|
||||
clash-verge-draft = { path = "crates/clash-verge-draft" }
|
||||
clash-verge-logging = { path = "crates/clash-verge-logging" }
|
||||
clash-verge-signal = { path = "crates/clash-verge-signal" }
|
||||
tauri = { version = "2.9.3" }
|
||||
parking_lot = { version = "0.12.5", features = [
|
||||
"hardware-lock-elision",
|
||||
"send_guard",
|
||||
|
||||
25
crates/clash-verge-signal/Cargo.toml
Normal file
25
crates/clash-verge-signal/Cargo.toml
Normal file
@@ -0,0 +1,25 @@
|
||||
[package]
|
||||
name = "clash-verge-signal"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
tauri = { workspace = true }
|
||||
clash-verge-logging = { workspace = true }
|
||||
log = { workspace = true }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
signal-hook = "0.3.18"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows-sys = { version = "0.61.2", features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics_Gdi",
|
||||
"Win32_System_SystemServices",
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
] }
|
||||
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
16
crates/clash-verge-signal/src/lib.rs
Normal file
16
crates/clash-verge-signal/src/lib.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
#[cfg(unix)]
|
||||
mod unix;
|
||||
#[cfg(windows)]
|
||||
mod windows;
|
||||
|
||||
pub fn register<F, Fut>(#[cfg(windows)] app_handle: &tauri::AppHandle, f: F)
|
||||
where
|
||||
F: Fn() -> Fut + Send + Sync + 'static,
|
||||
Fut: Future + Send + 'static,
|
||||
{
|
||||
#[cfg(unix)]
|
||||
unix::register(f);
|
||||
|
||||
#[cfg(windows)]
|
||||
windows::register(app_handle, f);
|
||||
}
|
||||
44
crates/clash-verge-signal/src/unix.rs
Normal file
44
crates/clash-verge-signal/src/unix.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
use signal_hook::{
|
||||
consts::{SIGHUP, SIGINT, SIGTERM},
|
||||
iterator::Signals,
|
||||
low_level,
|
||||
};
|
||||
|
||||
use clash_verge_logging::{Type, logging, logging_error};
|
||||
|
||||
pub fn register<F, Fut>(f: F)
|
||||
where
|
||||
F: Fn() -> Fut + Send + Sync + 'static,
|
||||
Fut: Future + Send + 'static,
|
||||
{
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let signals = [SIGTERM, SIGINT, SIGHUP];
|
||||
|
||||
let mut sigs = match Signals::new(signals) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
logging!(error, Type::System, "注册信号处理器失败: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
for signal in &mut sigs {
|
||||
let signal_to_str = |signal: i32| match signal {
|
||||
SIGTERM => "SIGTERM",
|
||||
SIGINT => "SIGINT",
|
||||
SIGHUP => "SIGHUP",
|
||||
_ => "UNKNOWN",
|
||||
};
|
||||
|
||||
logging!(info, Type::System, "捕获到信号 {}", signal_to_str(signal));
|
||||
|
||||
f().await;
|
||||
|
||||
logging_error!(
|
||||
Type::System,
|
||||
"信号 {:?} 默认处理失败",
|
||||
low_level::emulate_default_handler(signal)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
use tauri::Manager as _;
|
||||
use std::{future::Future, pin::Pin, sync::OnceLock};
|
||||
|
||||
use tauri::{AppHandle, Manager as _};
|
||||
use windows_sys::Win32::{
|
||||
Foundation::{HWND, LPARAM, LRESULT, WPARAM},
|
||||
UI::WindowsAndMessaging::{
|
||||
@@ -8,13 +10,17 @@ use windows_sys::Win32::{
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{core::handle, feat};
|
||||
use clash_verge_logging::{Type, logging};
|
||||
|
||||
// code refer to:
|
||||
// global-hotkey (https://github.com/tauri-apps/global-hotkey)
|
||||
// Global Shortcut (https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/global-shortcut)
|
||||
|
||||
type ShutdownHandler =
|
||||
Box<dyn Fn() -> Pin<Box<dyn std::future::Future<Output = ()> + Send>> + Send + Sync>;
|
||||
|
||||
static SHUTDOWN_HANDLER: OnceLock<ShutdownHandler> = OnceLock::new();
|
||||
|
||||
struct ShutdownState {
|
||||
hwnd: HWND,
|
||||
}
|
||||
@@ -49,11 +55,19 @@ unsafe extern "system" fn shutdown_proc(
|
||||
);
|
||||
}
|
||||
WM_ENDSESSION => {
|
||||
tauri::async_runtime::block_on(async move {
|
||||
logging!(info, Type::System, "Session ended, system shutting down.");
|
||||
feat::clean_async().await;
|
||||
logging!(info, Type::System, "resolved reset finished");
|
||||
});
|
||||
if let Some(handler) = SHUTDOWN_HANDLER.get() {
|
||||
tauri::async_runtime::block_on(async {
|
||||
logging!(info, Type::System, "Session ended, system shutting down.");
|
||||
handler().await;
|
||||
logging!(info, Type::System, "resolved reset finished");
|
||||
});
|
||||
} else {
|
||||
logging!(
|
||||
error,
|
||||
Type::System,
|
||||
"WM_ENDSESSION received but no shutdown handler is registered"
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
@@ -81,8 +95,18 @@ fn get_instance_handle() -> windows_sys::Win32::Foundation::HMODULE {
|
||||
unsafe { &__ImageBase as *const _ as _ }
|
||||
}
|
||||
|
||||
pub fn register() {
|
||||
let app_handle = handle::Handle::app_handle();
|
||||
pub fn register<F, Fut>(app_handle: &AppHandle, f: F)
|
||||
where
|
||||
F: Fn() -> Fut + Send + Sync + 'static,
|
||||
Fut: Future + Send + 'static,
|
||||
{
|
||||
let _ = SHUTDOWN_HANDLER.set(Box::new(move || {
|
||||
let fut = (f)();
|
||||
Box::pin(async move {
|
||||
fut.await;
|
||||
}) as Pin<Box<dyn std::future::Future<Output = ()> + Send>>
|
||||
}));
|
||||
|
||||
let class_name = encode_wide("global_shutdown_app");
|
||||
unsafe {
|
||||
let hinstance = get_instance_handle();
|
||||
@@ -32,6 +32,14 @@ tauri-build = { version = "2.5.2", features = [] }
|
||||
[dependencies]
|
||||
clash-verge-draft = { workspace = true }
|
||||
clash-verge-logging = { workspace = true }
|
||||
clash-verge-signal = { workspace = true }
|
||||
tauri = { workspace = true, features = [
|
||||
"protocol-asset",
|
||||
"devtools",
|
||||
"tray-icon",
|
||||
"image-ico",
|
||||
"image-png",
|
||||
] }
|
||||
parking_lot = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
@@ -57,13 +65,6 @@ regex = "1.12.2"
|
||||
sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs", features = [
|
||||
"guard",
|
||||
] }
|
||||
tauri = { version = "2.9.3", features = [
|
||||
"protocol-asset",
|
||||
"devtools",
|
||||
"tray-icon",
|
||||
"image-ico",
|
||||
"image-png",
|
||||
] }
|
||||
network-interface = { version = "2.0.3", features = ["serde"] }
|
||||
tauri-plugin-shell = "2.3.3"
|
||||
tauri-plugin-dialog = "2.4.2"
|
||||
@@ -115,15 +116,6 @@ winapi = { version = "0.3.9", features = [
|
||||
"winhttp",
|
||||
"winreg",
|
||||
] }
|
||||
windows-sys = { version = "0.61.2", features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics_Gdi",
|
||||
"Win32_System_SystemServices",
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
] }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
signal-hook = "0.3.18"
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-autostart = "2.5.1"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod auto_backup;
|
||||
pub mod lightweight;
|
||||
pub mod signal;
|
||||
pub mod sysinfo;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#[cfg(unix)]
|
||||
mod unix;
|
||||
#[cfg(windows)]
|
||||
mod windows;
|
||||
|
||||
pub fn register() {
|
||||
#[cfg(windows)]
|
||||
windows::register();
|
||||
|
||||
#[cfg(unix)]
|
||||
unix::register();
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
use signal_hook::{
|
||||
consts::{SIGHUP, SIGINT, SIGTERM},
|
||||
iterator::Signals,
|
||||
low_level,
|
||||
};
|
||||
|
||||
use crate::feat;
|
||||
use clash_verge_logging::{Type, logging, logging_error};
|
||||
|
||||
pub fn register() {
|
||||
tauri::async_runtime::spawn(async {
|
||||
let signals = [SIGTERM, SIGINT, SIGHUP];
|
||||
match Signals::new(signals) {
|
||||
Ok(mut sigs) => {
|
||||
for signal in &mut sigs {
|
||||
let signal_to_str = |signal: i32| match signal {
|
||||
SIGTERM => "SIGTERM",
|
||||
SIGINT => "SIGINT",
|
||||
SIGHUP => "SIGHUP",
|
||||
_ => "UNKNOWN",
|
||||
};
|
||||
logging!(info, Type::System, "捕获到信号 {}", signal_to_str(signal));
|
||||
feat::clean_async().await;
|
||||
// After printing it, do whatever the signal was supposed to do in the first place
|
||||
logging_error!(
|
||||
Type::System,
|
||||
"信号 {:?} 默认处理失败",
|
||||
low_level::emulate_default_handler(signal)
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
logging!(error, Type::System, "注册信号处理器失败: {}", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -9,11 +9,13 @@ use crate::{
|
||||
sysopt,
|
||||
tray::Tray,
|
||||
},
|
||||
module::{auto_backup::AutoBackupManager, lightweight::auto_lightweight_boot, signal},
|
||||
feat,
|
||||
module::{auto_backup::AutoBackupManager, lightweight::auto_lightweight_boot},
|
||||
process::AsyncHandler,
|
||||
utils::{init, server, window_manager::WindowManager},
|
||||
};
|
||||
use clash_verge_logging::{Type, logging, logging_error};
|
||||
use clash_verge_signal;
|
||||
|
||||
pub mod dns;
|
||||
pub mod scheme;
|
||||
@@ -134,7 +136,11 @@ pub(super) async fn init_auto_backup() {
|
||||
|
||||
pub(super) fn init_signal() {
|
||||
logging!(info, Type::Setup, "Initializing signal handlers...");
|
||||
signal::register();
|
||||
clash_verge_signal::register(
|
||||
#[cfg(windows)]
|
||||
handle::Handle::app_handle(),
|
||||
feat::clean_async,
|
||||
);
|
||||
}
|
||||
|
||||
pub async fn init_work_config() {
|
||||
|
||||
Reference in New Issue
Block a user