use std::sync::atomic::{AtomicBool, Ordering};
static SIGINT_PENDING: AtomicBool = AtomicBool::new(false);
static SIGTERM_PENDING: AtomicBool = AtomicBool::new(false);
static SIGHUP_PENDING: AtomicBool = AtomicBool::new(false);
pub fn name_to_signal(name: &str) -> Option<i32> {
let name = name.strip_prefix("SIG").unwrap_or(name);
match name {
"HUP" => Some(libc::SIGHUP),
"INT" => Some(libc::SIGINT),
"QUIT" => Some(libc::SIGQUIT),
"ILL" => Some(libc::SIGILL),
"TRAP" => Some(libc::SIGTRAP),
"ABRT" | "IOT" => Some(libc::SIGABRT),
"FPE" => Some(libc::SIGFPE),
"KILL" => Some(libc::SIGKILL),
"BUS" => Some(libc::SIGBUS),
"SEGV" => Some(libc::SIGSEGV),
"SYS" => Some(libc::SIGSYS),
"PIPE" => Some(libc::SIGPIPE),
"ALRM" => Some(libc::SIGALRM),
"TERM" => Some(libc::SIGTERM),
"URG" => Some(libc::SIGURG),
"STOP" => Some(libc::SIGSTOP),
"TSTP" => Some(libc::SIGTSTP),
"CONT" => Some(libc::SIGCONT),
"CHLD" => Some(libc::SIGCHLD),
"TTIN" => Some(libc::SIGTTIN),
"TTOU" => Some(libc::SIGTTOU),
"USR1" => Some(libc::SIGUSR1),
"USR2" => Some(libc::SIGUSR2),
_ => None,
}
}
pub fn signal_to_name(signum: i32) -> Option<&'static str> {
match signum {
libc::SIGHUP => Some("HUP"),
libc::SIGINT => Some("INT"),
libc::SIGQUIT => Some("QUIT"),
libc::SIGILL => Some("ILL"),
libc::SIGTRAP => Some("TRAP"),
libc::SIGABRT => Some("ABRT"),
libc::SIGFPE => Some("FPE"),
libc::SIGKILL => Some("KILL"),
libc::SIGBUS => Some("BUS"),
libc::SIGSEGV => Some("SEGV"),
libc::SIGSYS => Some("SYS"),
libc::SIGPIPE => Some("PIPE"),
libc::SIGALRM => Some("ALRM"),
libc::SIGTERM => Some("TERM"),
libc::SIGURG => Some("URG"),
libc::SIGSTOP => Some("STOP"),
libc::SIGTSTP => Some("TSTP"),
libc::SIGCONT => Some("CONT"),
libc::SIGCHLD => Some("CHLD"),
libc::SIGTTIN => Some("TTIN"),
libc::SIGTTOU => Some("TTOU"),
libc::SIGUSR1 => Some("USR1"),
libc::SIGUSR2 => Some("USR2"),
_ => None,
}
}
pub fn install_handler(signum: i32) {
unsafe {
let mut sa: libc::sigaction = std::mem::zeroed();
sa.sa_sigaction = signal_handler as *const () as usize;
sa.sa_flags = libc::SA_RESTART;
libc::sigemptyset(&mut sa.sa_mask);
libc::sigaction(signum, &sa, std::ptr::null_mut());
}
}
pub fn reset_handler(signum: i32) {
unsafe {
let mut sa: libc::sigaction = std::mem::zeroed();
sa.sa_sigaction = libc::SIG_DFL;
libc::sigemptyset(&mut sa.sa_mask);
libc::sigaction(signum, &sa, std::ptr::null_mut());
}
}
pub fn ignore_signal(signum: i32) {
unsafe {
let mut sa: libc::sigaction = std::mem::zeroed();
sa.sa_sigaction = libc::SIG_IGN;
libc::sigemptyset(&mut sa.sa_mask);
libc::sigaction(signum, &sa, std::ptr::null_mut());
}
}
pub fn take_pending() -> Vec<&'static str> {
let mut pending = Vec::new();
if SIGINT_PENDING.swap(false, Ordering::Relaxed) {
pending.push("INT");
}
if SIGTERM_PENDING.swap(false, Ordering::Relaxed) {
pending.push("TERM");
}
if SIGHUP_PENDING.swap(false, Ordering::Relaxed) {
pending.push("HUP");
}
pending
}
extern "C" fn signal_handler(signum: i32) {
match signum {
libc::SIGINT => SIGINT_PENDING.store(true, Ordering::Relaxed),
libc::SIGTERM => SIGTERM_PENDING.store(true, Ordering::Relaxed),
libc::SIGHUP => SIGHUP_PENDING.store(true, Ordering::Relaxed),
_ => {}
}
}