use std::mem::MaybeUninit;
use std::sync::Mutex;
use std::sync::atomic::Ordering;
use super::{MAX_SIGNAL, SIGNAL_FLAGS};
static SIGNAL_MUTEX: Mutex<()> = Mutex::new(());
extern "C" fn flag_signal_handler(sig: libc::c_int) {
let sig_num = sig as usize;
if sig_num < MAX_SIGNAL {
SIGNAL_FLAGS[sig_num].store(true, Ordering::Release);
}
}
pub(super) fn install_signal_handler(sig_num: libc::c_int) -> Result<(), std::io::Error> {
let _guard = SIGNAL_MUTEX
.lock()
.expect("signal: mutex poisoned during handler installation");
unsafe {
let mut action: libc::sigaction = MaybeUninit::zeroed().assume_init();
action.sa_sigaction = flag_signal_handler as *const () as libc::sighandler_t;
action.sa_flags = libc::SA_RESTART;
libc::sigemptyset(&mut action.sa_mask);
let result = libc::sigaction(sig_num, &action, std::ptr::null_mut());
if result != 0 {
return Err(std::io::Error::last_os_error());
}
}
Ok(())
}
pub(super) fn restore_default_handler(sig_num: libc::c_int) -> Result<(), std::io::Error> {
let _guard = SIGNAL_MUTEX
.lock()
.expect("signal: mutex poisoned during handler restoration");
unsafe {
let mut action: libc::sigaction = MaybeUninit::zeroed().assume_init();
action.sa_sigaction = libc::SIG_DFL as libc::sighandler_t;
action.sa_flags = 0;
libc::sigemptyset(&mut action.sa_mask);
let result = libc::sigaction(sig_num, &action, std::ptr::null_mut());
if result != 0 {
return Err(std::io::Error::last_os_error());
}
}
Ok(())
}
pub(super) fn ignore_signal(sig_num: libc::c_int) -> Result<(), std::io::Error> {
let _guard = SIGNAL_MUTEX
.lock()
.expect("signal: mutex poisoned during ignore");
unsafe {
let mut action: libc::sigaction = MaybeUninit::zeroed().assume_init();
action.sa_sigaction = libc::SIG_IGN as libc::sighandler_t;
action.sa_flags = 0;
libc::sigemptyset(&mut action.sa_mask);
let result = libc::sigaction(sig_num, &action, std::ptr::null_mut());
if result != 0 {
return Err(std::io::Error::last_os_error());
}
}
Ok(())
}