use tokio::sync::mpsc;
use crate::{SignalKind as PubSignalKind, SupervisorEvent};
const SIGNAL_CHANNEL_CAPACITY: usize = 16;
pub fn spawn_signal_source() -> mpsc::Receiver<SupervisorEvent> {
let (tx, rx) = mpsc::channel::<SupervisorEvent>(SIGNAL_CHANNEL_CAPACITY);
install_listeners(tx);
rx
}
#[cfg(unix)]
fn install_listeners(tx: mpsc::Sender<SupervisorEvent>) {
use tokio::signal::unix::{SignalKind, signal};
fn spawn_one(tx: mpsc::Sender<SupervisorEvent>, kind: SignalKind, tag: PubSignalKind) {
tokio::spawn(async move {
let Ok(mut stream) = signal(kind) else {
return;
};
while stream.recv().await.is_some() {
if tx.send(SupervisorEvent::SignalReceived(tag)).await.is_err() {
break;
}
}
});
}
spawn_one(
tx.clone(),
SignalKind::terminate(),
PubSignalKind::Terminate,
);
spawn_one(
tx.clone(),
SignalKind::interrupt(),
PubSignalKind::Interrupt,
);
spawn_one(
tx.clone(),
SignalKind::user_defined1(),
PubSignalKind::UserDefined1,
);
spawn_one(tx, SignalKind::hangup(), PubSignalKind::Hangup);
}
#[cfg(windows)]
fn install_listeners(tx: mpsc::Sender<SupervisorEvent>) {
use tokio::signal::windows::{ctrl_break, ctrl_c};
let tx_c = tx.clone();
tokio::spawn(async move {
let Ok(mut stream) = ctrl_c() else {
return;
};
while stream.recv().await.is_some() {
if tx_c
.send(SupervisorEvent::SignalReceived(PubSignalKind::Interrupt))
.await
.is_err()
{
break;
}
}
});
tokio::spawn(async move {
let Ok(mut stream) = ctrl_break() else {
return;
};
while stream.recv().await.is_some() {
if tx
.send(SupervisorEvent::SignalReceived(PubSignalKind::CtrlBreak))
.await
.is_err()
{
break;
}
}
});
}