Fix CancelableTask
This commit is contained in:
11
Cargo.lock
generated
11
Cargo.lock
generated
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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();
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user