Skip to main content

omni_dev/daemon/
lifecycle.rs

1//! Process-lifecycle wiring: translate OS termination signals into a graceful
2//! shutdown of the daemon's [`CancellationToken`].
3
4use tokio_util::sync::CancellationToken;
5
6/// Spawns a task that cancels `shutdown` when the process is asked to stop.
7///
8/// On Unix this listens for `SIGTERM` (what `launchctl bootout` and service
9/// managers send), `SIGINT` (Ctrl-C in a foreground `daemon run`), and
10/// `SIGHUP` (the default disposition would hard-kill; treating it as a
11/// graceful stop keeps the socket unlinked and services drained even though a
12/// `daemon start`-launched daemon sits in its own session and never sees a
13/// terminal hangup). Elsewhere it listens for Ctrl-C only.
14pub fn install_signal_handlers(shutdown: CancellationToken) {
15    #[cfg(unix)]
16    {
17        use tokio::signal::unix::{signal, SignalKind};
18        tokio::spawn(async move {
19            let mut term = match signal(SignalKind::terminate()) {
20                Ok(s) => s,
21                Err(e) => {
22                    tracing::warn!("failed to install SIGTERM handler: {e}");
23                    return;
24                }
25            };
26            let mut interrupt = match signal(SignalKind::interrupt()) {
27                Ok(s) => s,
28                Err(e) => {
29                    tracing::warn!("failed to install SIGINT handler: {e}");
30                    return;
31                }
32            };
33            let mut hangup = match signal(SignalKind::hangup()) {
34                Ok(s) => s,
35                Err(e) => {
36                    tracing::warn!("failed to install SIGHUP handler: {e}");
37                    return;
38                }
39            };
40            tokio::select! {
41                _ = term.recv() => tracing::info!("received SIGTERM; shutting down"),
42                _ = interrupt.recv() => tracing::info!("received SIGINT; shutting down"),
43                _ = hangup.recv() => tracing::info!("received SIGHUP; shutting down"),
44            }
45            shutdown.cancel();
46        });
47    }
48    #[cfg(not(unix))]
49    {
50        tokio::spawn(async move {
51            if tokio::signal::ctrl_c().await.is_ok() {
52                tracing::info!("received Ctrl-C; shutting down");
53                shutdown.cancel();
54            }
55        });
56    }
57}