use std::{fmt, io};
#[derive(Clone, Copy, Debug)]
pub(super) enum ShutdownSignal {
Interrupt,
#[cfg(unix)]
Terminate,
}
impl ShutdownSignal {
pub(super) fn exit_code(self) -> u8 {
match self {
Self::Interrupt => 130,
#[cfg(unix)]
Self::Terminate => 143,
}
}
}
impl fmt::Display for ShutdownSignal {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Interrupt => formatter.write_str("SIGINT"),
#[cfg(unix)]
Self::Terminate => formatter.write_str("SIGTERM"),
}
}
}
#[cfg(unix)]
pub(super) struct ShutdownSignals {
interrupt: tokio::signal::unix::Signal,
terminate: tokio::signal::unix::Signal,
}
#[cfg(unix)]
impl ShutdownSignals {
pub(super) fn install() -> io::Result<Self> {
use tokio::signal::unix::{signal, SignalKind};
Ok(Self {
interrupt: signal(SignalKind::interrupt())?,
terminate: signal(SignalKind::terminate())?,
})
}
pub(super) async fn recv(&mut self) -> io::Result<ShutdownSignal> {
tokio::select! {
_ = self.interrupt.recv() => Ok(ShutdownSignal::Interrupt),
_ = self.terminate.recv() => Ok(ShutdownSignal::Terminate),
}
}
}
#[cfg(windows)]
pub(super) struct ShutdownSignals {
ctrl_c: tokio::signal::windows::CtrlC,
}
#[cfg(windows)]
impl ShutdownSignals {
pub(super) fn install() -> io::Result<Self> {
Ok(Self {
ctrl_c: tokio::signal::windows::ctrl_c()?,
})
}
pub(super) async fn recv(&mut self) -> io::Result<ShutdownSignal> {
self.ctrl_c.recv().await;
Ok(ShutdownSignal::Interrupt)
}
}