use std::future::{pending, Future};
use tokio::signal::unix::{signal as register_unix_signal, Signal, SignalKind};
use tracing::{error, info};
pub fn signal() -> impl Future<Output = ()> {
let mut terminate = register_signal(SignalKind::terminate(), "SIGTERM");
let mut interrupt = register_signal(SignalKind::interrupt(), "SIGINT");
async move {
tokio::select! {
_ = receive_signal(&mut terminate) => {
info!(signal = "SIGTERM", "shutdown signal received");
}
_ = receive_signal(&mut interrupt) => {
info!(signal = "SIGINT", "shutdown signal received");
}
}
}
}
fn register_signal(kind: SignalKind, name: &'static str) -> Option<Signal> {
match register_unix_signal(kind) {
Ok(signal) => Some(signal),
Err(error) => {
error!(%error, signal = name, "failed to register shutdown signal");
None
}
}
}
async fn receive_signal(signal: &mut Option<Signal>) {
match signal {
Some(signal) => {
signal.recv().await;
}
None => pending().await,
}
}