| // Copyright 2023 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| //! Utilities for working with signal handlers |
| use libc::c_int; |
| use nix::sys::signal::pthread_sigmask; |
| use nix::sys::signal::sigaction; |
| use nix::sys::signal::SaFlags; |
| use nix::sys::signal::SigAction; |
| use nix::sys::signal::SigHandler; |
| use nix::sys::signal::SigSet; |
| use nix::sys::signal::SigmaskHow; |
| use nix::sys::signal::Signal; |
| |
| /// Registers `handler` as the signal handler of signum `num`. |
| /// |
| /// # Safety |
| /// |
| /// This is considered unsafe because the given handler will be called asynchronously, interrupting |
| /// whatever the thread was doing and therefore must only do async-signal-safe operations. |
| pub unsafe fn register_signal_handler( |
| num: Signal, |
| handler: extern "C" fn(c_int), |
| ) -> nix::Result<()> { |
| sigaction( |
| num, |
| &SigAction::new( |
| SigHandler::Handler(handler), |
| SaFlags::SA_RESTART, |
| SigSet::empty(), |
| ), |
| ) |
| .map(|_| ()) |
| } |
| |
| /// Resets the signal handler of signum `num` back to the default. |
| pub fn clear_signal_handler(num: Signal) -> nix::Result<()> { |
| // SAFETY: Reverting to SigDfl is safe, we are not setting a handler. |
| unsafe { |
| sigaction( |
| num, |
| &SigAction::new(SigHandler::SigDfl, SaFlags::SA_RESTART, SigSet::empty()), |
| ) |
| .map(|_| ()) |
| } |
| } |
| |
| /// Masks given signal. |
| pub fn block_signal(num: Signal) -> nix::Result<()> { |
| let mut sigset = SigSet::empty(); |
| sigset.add(num); |
| pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(&sigset), None) |
| } |
| |
| /// Unmasks given signal. |
| pub fn unblock_signal(num: Signal) -> nix::Result<()> { |
| let mut sigset = SigSet::empty(); |
| sigset.add(num); |
| pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(&sigset), None) |
| } |