Fix CancelableTask

This commit is contained in:
2026-03-10 17:01:49 -07:00
parent fd66a4995a
commit a05cf9da01
6 changed files with 29 additions and 30 deletions

View File

@@ -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]

View File

@@ -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 }

View File

@@ -94,8 +94,7 @@ async fn main_inner() -> Result<i32> {
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),

View File

@@ -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<JoinHandle<()>> {
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();
})
}