Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added sigaction_is_default(), sigaction_is_ignore(), and sigaction_current() functions #2190

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/2190.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added `sigaction_is_default()`, `sigaction_is_ignore()`, and `sigaction_current()` functions
46 changes: 41 additions & 5 deletions src/sys/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,16 @@ impl SigAction {
}
}

unsafe fn sigaction_inner(signal: Signal, sigaction: Option<&SigAction>) -> Result<SigAction> {
let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();

let res = libc::sigaction(signal as libc::c_int,
sigaction.map_or(ptr::null(), |sigaction| &sigaction.sigaction as *const libc::sigaction),
oldact.as_mut_ptr());

Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() })
}

/// Changes the action taken by a process on receipt of a specific signal.
///
/// `signal` can be any signal except `SIGKILL` or `SIGSTOP`. On success, it returns the previous
Expand All @@ -882,13 +892,39 @@ impl SigAction {
/// pointer is valid. In that case, this function effectively dereferences a
/// raw pointer of unknown provenance.
pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
sigaction_inner(signal, Some(sigaction))
}

let res = libc::sigaction(signal as libc::c_int,
&sigaction.sigaction as *const libc::sigaction,
oldact.as_mut_ptr());
/// Gets the current action a process will take on receipt of a specific signal.
///
/// `signal` can be any signal except `SIGKILL` or `SIGSTOP`. On success, it returns the current
/// action for the given signal. The current action will always remain in place, unchanged.
///
/// # Safety
///
/// There is no guarantee that the old signal handler was installed
/// correctly. If it was installed by this crate, it will be. But if it was
/// installed by, for example, C code, then there is no guarantee its function
/// pointer is valid. In that case, this function effectively dereferences a
/// raw pointer of unknown provenance.
pub unsafe fn sigaction_current(signal: Signal) -> Result<SigAction> {
sigaction_inner(signal, None)
}

Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() })
/// Whether the specified signal currently has its default action.
///
/// `signal` can be any signal except `SIGKILL` or `SIGSTOP`.
pub fn sigaction_is_default(signal: Signal) -> Result<bool> {
// SAFETY: fetching the current action is safe if the handler isn't called
unsafe { sigaction_current(signal) }.map(|sigaction| sigaction.handler() == SigHandler::SigDfl)
}

/// Whether the specified signal is currently ignored.
///
/// `signal` can be any signal except `SIGKILL` or `SIGSTOP`.
pub fn sigaction_is_ignore(signal: Signal) -> Result<bool> {
// SAFETY: fetching the current action is safe if the handler isn't called
unsafe { sigaction_current(signal) }.map(|sigaction| sigaction.handler() == SigHandler::SigIgn)
}

/// Signal management (see [signal(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
Expand Down
52 changes: 50 additions & 2 deletions test/sys/test_signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,56 @@ fn test_old_sigaction_flags() {
);
let oact = unsafe { sigaction(SIGINT, &act) }.unwrap();
let _flags = oact.flags();
let oact = unsafe { sigaction(SIGINT, &act) }.unwrap();
let _flags = oact.flags();
let _flags = unsafe { sigaction(SIGINT, &act) }.unwrap().flags();

// restore original
unsafe { sigaction(SIGINT, &oact) }.unwrap();
}

#[test]
fn test_current_sigaction() {
let _m = crate::SIGNAL_MTX.lock();

let oact = unsafe {
sigaction(
SIGINT,
&SigAction::new(
SigHandler::SigDfl,
SaFlags::empty(),
SigSet::empty(),
),
)
}
.unwrap();

assert_eq!(
unsafe { sigaction_current(SIGINT) }.unwrap().handler(),
SigHandler::SigDfl
);
assert!(sigaction_is_default(SIGINT).unwrap());
assert!(!sigaction_is_ignore(SIGINT).unwrap());

unsafe {
sigaction(
SIGINT,
&SigAction::new(
SigHandler::SigIgn,
SaFlags::empty(),
SigSet::empty(),
),
)
}
.unwrap();

assert_eq!(
unsafe { sigaction_current(SIGINT) }.unwrap().handler(),
SigHandler::SigIgn
);
assert!(!sigaction_is_default(SIGINT).unwrap());
assert!(sigaction_is_ignore(SIGINT).unwrap());

// restore original
unsafe { sigaction(SIGINT, &oact) }.unwrap();
}

#[test]
Expand Down