From a05cf9da0153b6bd5bee5615027a94b3462ef9d8 Mon Sep 17 00:00:00 2001 From: rm-dr <96270320+rm-dr@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:01:49 -0700 Subject: [PATCH] Fix `CancelableTask` --- Cargo.lock | 11 ------- Cargo.toml | 1 - crates/pile-toolbox/src/cancelabletask.rs | 4 ++- crates/pile/Cargo.toml | 1 - crates/pile/src/main.rs | 3 +- crates/pile/src/signal.rs | 39 +++++++++++++++-------- 6 files changed, 29 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cbc72e6..b508c27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2385,7 +2385,6 @@ dependencies = [ "pile-toolbox", "serde", "serde_json", - "signal-hook", "tokio", "tokio-stream", "toml", @@ -3037,16 +3036,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b57709da74f9ff9f4a27dce9526eec25ca8407c45a7887243b031a58935fb8e" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" version = "1.4.8" diff --git a/Cargo.toml b/Cargo.toml index fa52637..1b81f37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -117,7 +117,6 @@ kamadak-exif = "0.6.1" thiserror = "2.0.18" anyhow = "1.0.102" itertools = "0.14.0" -signal-hook = "0.4.3" rand = "0.10.0" strum = { version = "0.27.2", features = ["derive"] } walkdir = "2.5.0" diff --git a/crates/pile-toolbox/src/cancelabletask.rs b/crates/pile-toolbox/src/cancelabletask.rs index 64b9ec6..d91f879 100644 --- a/crates/pile-toolbox/src/cancelabletask.rs +++ b/crates/pile-toolbox/src/cancelabletask.rs @@ -80,8 +80,10 @@ impl CancelFlag { #[inline] pub async fn await_cancel(&self) { + if self.is_cancelled() { + return; + } self.notify.notified().await; - assert!(self.is_cancelled()); } #[inline] diff --git a/crates/pile/Cargo.toml b/crates/pile/Cargo.toml index 35c18e1..b0ef0d5 100644 --- a/crates/pile/Cargo.toml +++ b/crates/pile/Cargo.toml @@ -22,7 +22,6 @@ serde = { workspace = true } anyhow = { workspace = true } indicatif = { workspace = true } tracing-indicatif = { workspace = true } -signal-hook = { workspace = true } anstyle = { workspace = true } toml = { workspace = true } serde_json = { workspace = true } diff --git a/crates/pile/src/main.rs b/crates/pile/src/main.rs index 2e6a894..30515fc 100644 --- a/crates/pile/src/main.rs +++ b/crates/pile/src/main.rs @@ -94,8 +94,7 @@ async fn main_inner() -> Result { let ctx = GlobalContext { mp }; let task = cli.cmd.start(ctx).context("while starting task")?; - let signal_task = - start_signal_task(task.flag().clone()).context("while starting signal task")?; + let signal_task = start_signal_task(task.flag().clone()); match task.join().await { Ok(CancelableTaskResult::Finished(Ok(code))) => Ok(code), diff --git a/crates/pile/src/signal.rs b/crates/pile/src/signal.rs index 73af380..4af280a 100644 --- a/crates/pile/src/signal.rs +++ b/crates/pile/src/signal.rs @@ -1,24 +1,35 @@ -use anyhow::{Context, Result}; use pile_toolbox::cancelabletask::CancelFlag; -use signal_hook::{consts::TERM_SIGNALS, iterator::Signals}; use tokio::task::JoinHandle; use tracing::warn; /// Start an async task that listens for OS signals, /// setting `should_exit` to `true` when an exit signal /// is caught. -pub fn start_signal_task(flag: CancelFlag) -> Result> { - let mut signals = Signals::new(TERM_SIGNALS).context("Failed to initialize signal handler")?; - - let task = tokio::task::spawn_blocking(move || { - for sig in signals.forever() { - if TERM_SIGNALS.contains(&sig) { - warn!("Received signal {sig}, trying to exit cleanly"); - flag.cancel(); - break; +#[expect(clippy::expect_used)] +pub fn start_signal_task(flag: CancelFlag) -> JoinHandle<()> { + tokio::spawn(async move { + #[cfg(unix)] + { + use tokio::signal::unix::{SignalKind, signal}; + let mut sigterm = + signal(SignalKind::terminate()).expect("Failed to install SIGTERM handler"); + tokio::select! { + r = tokio::signal::ctrl_c() => { + if let Err(e) = r { tracing::error!("ctrl_c error: {e}"); } + warn!("Received SIGINT, exiting cleanly"); + } + _ = sigterm.recv() => { + warn!("Received SIGTERM, exiting cleanly"); + } } } - }); - - return Ok(task); + #[cfg(not(unix))] + { + if let Err(e) = tokio::signal::ctrl_c().await { + tracing::error!("ctrl_c error: {e}"); + } + warn!("Received Ctrl+C, exiting cleanly"); + } + flag.cancel(); + }) }