use std::os::raw::c_int;
use std::sync::atomic::{AtomicBool, Ordering};
use crate::error::{Error, Result};
const SIGINT: c_int = 2;
const SIGTERM: c_int = 15;
static TERMINATED: AtomicBool = AtomicBool::new(false);
#[repr(C)]
struct SigAction {
sa_handler: extern "C" fn(c_int),
sa_mask: [u64; 16], sa_flags: c_int,
sa_restorer: usize,
}
unsafe extern "C" {
fn sigaction(sig: c_int, act: *const SigAction, old: *mut SigAction) -> c_int;
}
extern "C" fn on_signal(_sig: c_int) {
TERMINATED.store(true, Ordering::SeqCst);
}
pub fn install() -> Result<()> {
let act = SigAction {
sa_handler: on_signal,
sa_mask: [0u64; 16],
sa_flags: 0,
sa_restorer: 0,
};
for sig in [SIGINT, SIGTERM] {
let r = unsafe { sigaction(sig, &act, std::ptr::null_mut()) };
if r < 0 {
return Err(Error::signal(format!(
"sigaction({sig}): {}",
std::io::Error::last_os_error()
)));
}
}
Ok(())
}
pub fn terminated() -> bool {
TERMINATED.load(Ordering::SeqCst)
}
#[cfg(test)]
pub(crate) fn reset_for_test() {
TERMINATED.store(false, Ordering::SeqCst);
}
#[cfg(test)]
pub(crate) fn set_for_test() {
TERMINATED.store(true, Ordering::SeqCst);
}