use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;
static STOP: AtomicBool = AtomicBool::new(false);
#[cfg(unix)]
extern "C" fn on_signal(_signal: libc::c_int) {
if STOP.swap(true, Ordering::SeqCst) {
unsafe { libc::_exit(130) };
}
}
pub fn install() {
#[cfg(unix)]
unsafe {
libc::signal(libc::SIGINT, on_signal as *const () as libc::sighandler_t);
libc::signal(libc::SIGTERM, on_signal as *const () as libc::sighandler_t);
}
}
pub fn received() -> bool {
STOP.load(Ordering::SeqCst)
}
pub fn on_stop(stop: impl FnOnce() -> bool + Send + 'static) {
install();
thread::Builder::new()
.name("stop-signal".into())
.spawn(move || {
while !received() {
thread::sleep(Duration::from_millis(100));
}
log::info!("stopping on signal");
let clean = stop();
crate::engine::summarize_incomplete();
std::process::exit(if clean { 0 } else { 1 });
})
.expect("spawn stop-signal watcher");
}