//! Unix startup and shutdown. //! //! There is no supervisor protocol to speak: systemd starts the process, and stops it by sending //! `SIGTERM`. All this module does is translate the two signals that mean "stop" into the future //! [`crate::app::run`] waits on, so a `systemctl stop` unwinds the same way a Ctrl-C does instead //! of being killed by the default `SIGTERM` disposition mid-write. use tokio::signal::unix::{signal, SignalKind}; pub fn run(config_path: Option<&str>) -> anyhow::Result<()> { crate::init_console_tracing(); tokio::runtime::Runtime::new()?.block_on(crate::app::run(config_path, || {}, shutdown_signal())) } /// Resolves on the first `SIGINT` or `SIGTERM`. async fn shutdown_signal() { // A failure to install a handler is not worth aborting a running sidecar for: fall back to // pending, which leaves that signal's default disposition (terminate) in place. let mut term = match signal(SignalKind::terminate()) { Ok(s) => s, Err(e) => { tracing::warn!(error = %e, "could not listen for SIGTERM"); std::future::pending::<()>().await; unreachable!() } }; let mut int = match signal(SignalKind::interrupt()) { Ok(s) => s, Err(e) => { tracing::warn!(error = %e, "could not listen for SIGINT"); term.recv().await; return; } }; tokio::select! { _ = term.recv() => tracing::info!("SIGTERM received"), _ = int.recv() => tracing::info!("SIGINT received"), } }