use super::super::Result;
use super::Disposition;
use super::ErrnoIfM1 as _;
pub use crate::signal::*;
use std::ffi::c_int;
use std::mem::MaybeUninit;
use std::ops::RangeInclusive;
#[must_use]
pub fn rt_range() -> RangeInclusive<RawNumber> {
#[cfg(target_os = "aix")]
return libc::SIGRTMIN..=libc::SIGRTMAX;
#[cfg(any(
target_os = "android",
target_os = "emscripten",
target_os = "l4re",
target_os = "linux",
))]
return libc::SIGRTMIN()..=libc::SIGRTMAX();
#[allow(unreachable_code, reason = "for readability")] #[allow(clippy::reversed_empty_ranges, reason = "false positive")]
return 0..=-1;
}
#[derive(Clone, Debug)]
#[repr(transparent)]
pub struct Sigset(pub(super) MaybeUninit<libc::sigset_t>);
impl Sigset {
pub(super) const unsafe fn from_raw(sigset: MaybeUninit<libc::sigset_t>) -> Self {
Self(sigset)
}
}
impl Default for Sigset {
fn default() -> Self {
let mut sigset = MaybeUninit::<libc::sigset_t>::uninit();
unsafe {
libc::sigemptyset(sigset.as_mut_ptr())
.errno_if_m1()
.expect("sigemptyset should always succeed");
Self::from_raw(sigset)
}
}
}
impl super::super::Sigset for Sigset {
fn full() -> Self {
let mut sigset = MaybeUninit::<libc::sigset_t>::uninit();
unsafe {
libc::sigfillset(sigset.as_mut_ptr())
.errno_if_m1()
.expect("sigfillset should always succeed");
Self::from_raw(sigset)
}
}
fn insert(&mut self, signal: Number) -> Result<()> {
let result = unsafe { libc::sigaddset(self.0.as_mut_ptr(), signal.as_raw()) };
result.errno_if_m1().map(drop)
}
fn remove(&mut self, signal: Number) -> Result<()> {
let result = unsafe { libc::sigdelset(self.0.as_mut_ptr(), signal.as_raw()) };
result.errno_if_m1().map(drop)
}
fn contains(&self, signal: Number) -> Result<bool> {
let result = unsafe { libc::sigismember(self.0.as_ptr(), signal.as_raw()) };
result.errno_if_m1().map(|r| r > 0)
}
}
impl Disposition {
pub(super) fn to_sigaction(self) -> MaybeUninit<libc::sigaction> {
let handler = match self {
Disposition::Default => libc::SIG_DFL,
Disposition::Ignore => libc::SIG_IGN,
Disposition::Catch => super::catch_signal as *const extern "C" fn(c_int) as _,
};
let mut sa = MaybeUninit::<libc::sigaction>::uninit();
let sa_ptr = sa.as_mut_ptr();
unsafe {
(&raw mut (*sa_ptr).sa_flags).write(0);
libc::sigemptyset(&raw mut (*sa_ptr).sa_mask);
#[cfg(not(target_os = "aix"))]
#[allow(
clippy::useless_transmute,
reason = "the type of sa_sigaction may vary across platforms"
)]
(&raw mut (*sa_ptr).sa_sigaction).write(std::mem::transmute(handler));
#[cfg(target_os = "aix")]
#[allow(
clippy::useless_transmute,
reason = "the type of __su_sigaction may vary across platforms"
)]
(&raw mut (*sa_ptr).sa_union.__su_sigaction).write(std::mem::transmute(handler));
}
sa
}
pub(super) unsafe fn from_sigaction(sa: &MaybeUninit<libc::sigaction>) -> Self {
unsafe {
#[cfg(not(target_os = "aix"))]
let handler = (*sa.as_ptr()).sa_sigaction;
#[cfg(target_os = "aix")]
let handler = (*sa.as_ptr()).sa_union.__su_sigaction;
#[allow(
clippy::useless_transmute,
reason = "the type of handler may vary across platforms"
)]
match std::mem::transmute(handler) {
libc::SIG_DFL => Self::Default,
libc::SIG_IGN => Self::Ignore,
_ => Self::Catch,
}
}
}
}