mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-16 23:40:32 +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:
parent
16478d314b
commit
e672d19622
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -1117,6 +1117,7 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"clash-verge-draft",
|
"clash-verge-draft",
|
||||||
"clash-verge-logging",
|
"clash-verge-logging",
|
||||||
|
"clash-verge-signal",
|
||||||
"clash_verge_logger",
|
"clash_verge_logger",
|
||||||
"clash_verge_service_ipc",
|
"clash_verge_service_ipc",
|
||||||
"compact_str",
|
"compact_str",
|
||||||
@ -1147,7 +1148,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml_ng",
|
"serde_yaml_ng",
|
||||||
"signal-hook 0.3.18",
|
|
||||||
"smartstring",
|
"smartstring",
|
||||||
"sys-locale",
|
"sys-locale",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
@ -1172,7 +1172,6 @@ dependencies = [
|
|||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"warp",
|
"warp",
|
||||||
"winapi",
|
"winapi",
|
||||||
"windows-sys 0.61.2",
|
|
||||||
"winreg 0.55.0",
|
"winreg 0.55.0",
|
||||||
"zip 6.0.0",
|
"zip 6.0.0",
|
||||||
]
|
]
|
||||||
@ -1197,6 +1196,17 @@ dependencies = [
|
|||||||
"tokio",
|
"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]]
|
[[package]]
|
||||||
name = "clash_verge_logger"
|
name = "clash_verge_logger"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
|||||||
@ -3,6 +3,7 @@ members = [
|
|||||||
"src-tauri",
|
"src-tauri",
|
||||||
"crates/clash-verge-draft",
|
"crates/clash-verge-draft",
|
||||||
"crates/clash-verge-logging",
|
"crates/clash-verge-logging",
|
||||||
|
"crates/clash-verge-signal",
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
@ -42,6 +43,8 @@ strip = false
|
|||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
clash-verge-draft = { path = "crates/clash-verge-draft" }
|
clash-verge-draft = { path = "crates/clash-verge-draft" }
|
||||||
clash-verge-logging = { path = "crates/clash-verge-logging" }
|
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 = [
|
parking_lot = { version = "0.12.5", features = [
|
||||||
"hardware-lock-elision",
|
"hardware-lock-elision",
|
||||||
"send_guard",
|
"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::{
|
use windows_sys::Win32::{
|
||||||
Foundation::{HWND, LPARAM, LRESULT, WPARAM},
|
Foundation::{HWND, LPARAM, LRESULT, WPARAM},
|
||||||
UI::WindowsAndMessaging::{
|
UI::WindowsAndMessaging::{
|
||||||
@ -8,13 +10,17 @@ use windows_sys::Win32::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{core::handle, feat};
|
|
||||||
use clash_verge_logging::{Type, logging};
|
use clash_verge_logging::{Type, logging};
|
||||||
|
|
||||||
// code refer to:
|
// code refer to:
|
||||||
// global-hotkey (https://github.com/tauri-apps/global-hotkey)
|
// global-hotkey (https://github.com/tauri-apps/global-hotkey)
|
||||||
// Global Shortcut (https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/global-shortcut)
|
// 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 {
|
struct ShutdownState {
|
||||||
hwnd: HWND,
|
hwnd: HWND,
|
||||||
}
|
}
|
||||||
@ -49,11 +55,19 @@ unsafe extern "system" fn shutdown_proc(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
WM_ENDSESSION => {
|
WM_ENDSESSION => {
|
||||||
tauri::async_runtime::block_on(async move {
|
if let Some(handler) = SHUTDOWN_HANDLER.get() {
|
||||||
logging!(info, Type::System, "Session ended, system shutting down.");
|
tauri::async_runtime::block_on(async {
|
||||||
feat::clean_async().await;
|
logging!(info, Type::System, "Session ended, system shutting down.");
|
||||||
logging!(info, Type::System, "resolved reset finished");
|
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 _ }
|
unsafe { &__ImageBase as *const _ as _ }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register() {
|
pub fn register<F, Fut>(app_handle: &AppHandle, f: F)
|
||||||
let app_handle = handle::Handle::app_handle();
|
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");
|
let class_name = encode_wide("global_shutdown_app");
|
||||||
unsafe {
|
unsafe {
|
||||||
let hinstance = get_instance_handle();
|
let hinstance = get_instance_handle();
|
||||||
@ -32,6 +32,14 @@ tauri-build = { version = "2.5.2", features = [] }
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
clash-verge-draft = { workspace = true }
|
clash-verge-draft = { workspace = true }
|
||||||
clash-verge-logging = { 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 }
|
parking_lot = { workspace = true }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
@ -57,13 +65,6 @@ regex = "1.12.2"
|
|||||||
sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs", features = [
|
sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs", features = [
|
||||||
"guard",
|
"guard",
|
||||||
] }
|
] }
|
||||||
tauri = { version = "2.9.3", features = [
|
|
||||||
"protocol-asset",
|
|
||||||
"devtools",
|
|
||||||
"tray-icon",
|
|
||||||
"image-ico",
|
|
||||||
"image-png",
|
|
||||||
] }
|
|
||||||
network-interface = { version = "2.0.3", features = ["serde"] }
|
network-interface = { version = "2.0.3", features = ["serde"] }
|
||||||
tauri-plugin-shell = "2.3.3"
|
tauri-plugin-shell = "2.3.3"
|
||||||
tauri-plugin-dialog = "2.4.2"
|
tauri-plugin-dialog = "2.4.2"
|
||||||
@ -115,15 +116,6 @@ winapi = { version = "0.3.9", features = [
|
|||||||
"winhttp",
|
"winhttp",
|
||||||
"winreg",
|
"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]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
tauri-plugin-autostart = "2.5.1"
|
tauri-plugin-autostart = "2.5.1"
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
pub mod auto_backup;
|
pub mod auto_backup;
|
||||||
pub mod lightweight;
|
pub mod lightweight;
|
||||||
pub mod signal;
|
|
||||||
pub mod sysinfo;
|
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,
|
sysopt,
|
||||||
tray::Tray,
|
tray::Tray,
|
||||||
},
|
},
|
||||||
module::{auto_backup::AutoBackupManager, lightweight::auto_lightweight_boot, signal},
|
feat,
|
||||||
|
module::{auto_backup::AutoBackupManager, lightweight::auto_lightweight_boot},
|
||||||
process::AsyncHandler,
|
process::AsyncHandler,
|
||||||
utils::{init, server, window_manager::WindowManager},
|
utils::{init, server, window_manager::WindowManager},
|
||||||
};
|
};
|
||||||
use clash_verge_logging::{Type, logging, logging_error};
|
use clash_verge_logging::{Type, logging, logging_error};
|
||||||
|
use clash_verge_signal;
|
||||||
|
|
||||||
pub mod dns;
|
pub mod dns;
|
||||||
pub mod scheme;
|
pub mod scheme;
|
||||||
@ -134,7 +136,11 @@ pub(super) async fn init_auto_backup() {
|
|||||||
|
|
||||||
pub(super) fn init_signal() {
|
pub(super) fn init_signal() {
|
||||||
logging!(info, Type::Setup, "Initializing signal handlers...");
|
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() {
|
pub async fn init_work_config() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user