50 lines
1.3 KiB
Rust
50 lines
1.3 KiB
Rust
#[cfg(unix)]
|
|
use tokio::signal::unix::signal;
|
|
use tokio::sync::broadcast;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum Interrupted {
|
|
OsSigInt,
|
|
UserInt,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct Terminator {
|
|
interrupt_tx: broadcast::Sender<Interrupted>,
|
|
}
|
|
|
|
impl Terminator {
|
|
pub fn new(interrupt_tx: broadcast::Sender<Interrupted>) -> Self {
|
|
Self { interrupt_tx }
|
|
}
|
|
|
|
pub fn terminate(&mut self, interrupted: Interrupted) -> anyhow::Result<()> {
|
|
self.interrupt_tx.send(interrupted)?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
async fn terminate_by_unix_signal(mut terminator: Terminator) {
|
|
let mut interrupt_signal = signal(tokio::signal::unix::SignalKind::interrupt())
|
|
.expect("failed to create interrupt signal stream");
|
|
|
|
interrupt_signal.recv().await;
|
|
|
|
terminator
|
|
.terminate(Interrupted::OsSigInt)
|
|
.expect("failed to send interrupt signal");
|
|
}
|
|
|
|
// create a broadcast channel for retrieving the application kill signal
|
|
pub fn create_termination() -> (Terminator, broadcast::Receiver<Interrupted>) {
|
|
let (tx, rx) = broadcast::channel(1);
|
|
let terminator = Terminator::new(tx);
|
|
|
|
#[cfg(unix)]
|
|
tokio::spawn(terminate_by_unix_signal(terminator.clone()));
|
|
|
|
(terminator, rx)
|
|
}
|