#[cfg(windows)]
mod platform {
use std::sync::Mutex;
use std::sync::mpsc::{Receiver, SyncSender, sync_channel};
use windows_sys::Win32::Foundation::{BOOL, TRUE};
use windows_sys::Win32::System::Console::SetConsoleCtrlHandler;
lazy_static! {
static ref CHANNEL: (SyncSender<u32>, Mutex<Receiver<u32>>) = {
let channel = sync_channel(0);
(channel.0, Mutex::new(channel.1))
};
}
unsafe extern "system" fn handler(event: u32) -> BOOL {
CHANNEL.0.send(event).unwrap();
CHANNEL.0.send(0).unwrap();
TRUE
}
pub struct ShutdownSignal;
impl ShutdownSignal {
pub fn new() -> ShutdownSignal {
unsafe { SetConsoleCtrlHandler(Some(handler), TRUE) };
ShutdownSignal
}
pub fn at_exit<F: FnOnce(usize)>(&self, handler: F) {
let event = {
let receiver = CHANNEL.1.lock().unwrap();
receiver.recv().unwrap()
};
handler(event as usize);
CHANNEL.1.lock().unwrap().recv().unwrap();
}
}
}
#[cfg(unix)]
mod platform {
use nix::sys::signal::{SIGINT, SIGQUIT, SIGTERM, SigSet};
pub struct ShutdownSignal(SigSet);
impl ShutdownSignal {
pub fn new() -> ShutdownSignal {
let mut mask = SigSet::empty();
ShutdownSignal::init(&mut mask).unwrap();
ShutdownSignal(mask)
}
fn init(mask: &mut SigSet) -> nix::Result<()> {
mask.add(SIGINT);
mask.add(SIGQUIT);
mask.add(SIGTERM);
mask.thread_block()
}
pub fn at_exit<F: FnOnce(usize)>(&self, handler: F) {
let signal = self.0.wait().unwrap();
handler(signal as usize);
}
}
}
pub use platform::ShutdownSignal;