use nix::sys::signal::{self, SaFlags, SigAction, SigHandler};
pub struct SaGuard<const N: usize> {
old_sigactions: [(signal::Signal, signal::SigAction); N],
old_sigmask: signal::SigSet,
}
impl<const N: usize> SaGuard<N> {
pub fn new(signals: &[signal::Signal; N]) -> anyhow::Result<Self> {
let mut suppressed_signals = signal::SigSet::empty();
for signal in signals {
suppressed_signals.add(*signal);
}
let mut old_sigmask = signal::SigSet::empty();
signal::sigprocmask(
signal::SigmaskHow::SIG_BLOCK,
Some(&suppressed_signals),
Some(&mut old_sigmask),
)?;
let mut old_sigactions = [(
signal::Signal::SIGINT,
SigAction::new(
SigHandler::SigDfl,
SaFlags::empty(),
signal::SigSet::empty(),
),
); N];
for (i, &signal) in signals.iter().enumerate() {
let old_sigaction = unsafe {
signal::sigaction(
signal,
&SigAction::new(
SigHandler::SigIgn,
SaFlags::empty(),
signal::SigSet::empty(),
),
)?
};
old_sigactions[i] = (signal, old_sigaction);
}
Ok(Self {
old_sigactions,
old_sigmask,
})
}
}
impl<const N: usize> Drop for SaGuard<N> {
fn drop(&mut self) {
for &(signal, old_sigaction) in &self.old_sigactions {
unsafe {
let _ = signal::sigaction(signal, &old_sigaction);
}
}
let _ = signal::sigprocmask(
signal::SigmaskHow::SIG_SETMASK,
Some(&self.old_sigmask),
None,
);
}
}