diff --git a/Cargo.lock b/Cargo.lock index cd745ae1..d61ddbf8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -144,7 +144,6 @@ dependencies = [ "concat-string", "core-foundation", "crossterm", - "ctrlc", "dirs", "fern", "filedescriptor", @@ -166,6 +165,7 @@ dependencies = [ "schemars", "serde", "serde_json", + "signal-hook 0.4.4", "starship-battery", "strum 0.27.2", "sysctl", @@ -380,7 +380,7 @@ dependencies = [ "mio", "parking_lot", "rustix", - "signal-hook", + "signal-hook 0.3.18", "signal-hook-mio", "winapi", ] @@ -394,17 +394,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "ctrlc" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" -dependencies = [ - "dispatch2", - "nix 0.30.1", - "windows-sys 0.61.2", -] - [[package]] name = "darling" version = "0.20.11" @@ -540,7 +529,6 @@ checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.13.0", "block2", - "libc", "objc2", ] @@ -901,18 +889,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags 2.13.0", - "cfg-if", - "cfg_aliases 0.2.1", - "libc", -] - [[package]] name = "nix" version = "0.31.3" @@ -1546,6 +1522,16 @@ dependencies = [ "signal-hook-registry", ] +[[package]] +name = "signal-hook" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a0c28ca5908dbdbcd52e6fdaa00358ab88637f8ab33e1f188dd510eb44b53d" +dependencies = [ + "libc", + "signal-hook-registry", +] + [[package]] name = "signal-hook-mio" version = "0.2.5" @@ -1554,7 +1540,7 @@ checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" dependencies = [ "libc", "mio", - "signal-hook", + "signal-hook 0.3.18", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 13bde760..45ee437a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,7 +71,6 @@ anyhow = "1.0.101" clap = { version = "4.6.1", features = ["default", "cargo", "wrap_help", "derive"] } concat-string = "1.0.1" crossterm = "0.29.0" -ctrlc = { version = "3.5.0", features = ["termination"] } dirs = "6.0.0" humantime = "2.3.0" indexmap = "2.14.0" @@ -87,6 +86,7 @@ ratatui-core = "0.1.2" regex = "1.12.3" rustc-hash = "2.1.2" serde = { version = "1.0.228", features = ["derive"] } +signal-hook = "0.4.4" starship-battery = { version = "0.11.0", optional = true } sysinfo = "=0.39.5" timeless = "0.0.14-alpha" diff --git a/src/lib.rs b/src/lib.rs index 28316b3b..70189c0f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -395,12 +395,33 @@ pub fn start_bottom(enable_error_hook: &mut bool) -> anyhow::Result<()> { // Set panic hook panic::set_hook(Box::new(panic_hook)); - // Set termination hook - ctrlc::set_handler(move || { - // TODO: Consider using signal-hook (https://github.com/vorner/signal-hook) to handle - // more types of signals? - let _ = sender.send(BottomEvent::Terminate); - })?; + // Set termination hook. + const SIGNALS: &[i32] = { + use signal_hook::consts::*; + cfg_select! { + target_os = "windows" => &[SIGTERM, SIGINT], + _ => &[SIGTERM, SIGQUIT, SIGINT, SIGHUP], + } + }; + + for signal in SIGNALS { + let sender = sender.clone(); + + // SAFETY: This is safe as: + // - We are _not_ calling a non-async-signal-safe function, just sending a message via a channel. + // - We are _not_ accessing globals or thread-locals at all. + // - The sender can't panic, and we swallow the error if there is one. + // + // See https://docs.rs/signal-hook/latest/signal_hook/low_level/fn.register.html#safety. + // + // We are also not worried about panic behaviour, as we are not catching any of the FORBIDDEN signals (SIGKILL, + // SIGSTOP, SIGILL, SIGFPE, SIGSEGV). See https://docs.rs/signal-hook/latest/signal_hook/low_level/fn.register.html#panics + unsafe { + signal_hook::low_level::register(*signal, move || { + let _ = sender.send(BottomEvent::Terminate); + })?; + } + } let mut first_run = true;