pub(crate) struct SignalDispositionGuard {
saved: Vec<(i32, libc::sighandler_t)>,
}
impl SignalDispositionGuard {
pub(crate) fn new() -> Self {
Self { saved: Vec::new() }
}
#[cfg(feature = "unix-runtime")]
pub(crate) fn set(&mut self, sig: i32, disposition: libc::sighandler_t) -> bool {
if !configurable_signal(sig) {
return false;
}
let previous = unsafe { libc::signal(sig, disposition) };
if previous == libc::SIG_ERR {
return false;
}
self.saved.push((sig, previous));
true
}
#[cfg(any(
feature = "frontend",
all(
test,
feature = "embed",
feature = "test-support",
feature = "unix-runtime"
)
))]
pub(crate) fn set_preserving_ignore(
&mut self,
sig: i32,
disposition: libc::sighandler_t,
) -> bool {
if !configurable_signal(sig) {
return false;
}
let previous = unsafe { libc::signal(sig, disposition) };
if previous == libc::SIG_ERR {
return false;
}
if previous == libc::SIG_IGN {
unsafe {
let _ = libc::signal(sig, libc::SIG_IGN);
}
return false;
}
self.saved.push((sig, previous));
true
}
}
impl Drop for SignalDispositionGuard {
fn drop(&mut self) {
for (sig, handler) in self.saved.drain(..).rev() {
unsafe {
let _ = libc::signal(sig, handler);
}
}
}
}
fn configurable_signal(sig: i32) -> bool {
sig > 0 && sig != libc::SIGKILL && sig != libc::SIGSTOP
}