Use unsafe blocks in signal.h implementation

This commit is contained in:
sourceturner
2026-01-16 22:14:06 +01:00
committed by sourceturner
parent a426887528
commit b3add24654
+71 -60
View File
@@ -2,6 +2,9 @@
//!
//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/signal.h.html>.
// TODO: set this for entire crate when possible
#![deny(unsafe_op_in_unsafe_fn)]
use core::{arch::global_asm, mem, ptr};
use cbitset::BitSet;
@@ -141,16 +144,16 @@ unsafe extern "C" {
unsafe extern "C" fn __sigsetjmp_tail(jb: *mut u64, ret: i32) -> i32 {
let set = jb.wrapping_add(9);
if ret > 0 {
sigprocmask(SIG_SETMASK, set, ptr::null_mut());
unsafe { sigprocmask(SIG_SETMASK, set, ptr::null_mut()) };
} else {
sigprocmask(SIG_SETMASK, ptr::null_mut(), set);
unsafe { sigprocmask(SIG_SETMASK, ptr::null_mut(), set) };
}
ret
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn siglongjmp(jb: *mut u64, ret: i32) {
setjmp::longjmp(jb, ret);
unsafe { setjmp::longjmp(jb, ret) };
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/kill.html>.
@@ -177,10 +180,10 @@ pub extern "C" fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_kill(thread: pthread_t, sig: c_int) -> c_int {
let os_tid = {
let pthread = &*(thread as *const crate::pthread::Pthread);
pthread.os_tid.get().read()
let pthread = unsafe { &*(thread as *const crate::pthread::Pthread) };
unsafe { pthread.os_tid.get().read() }
};
crate::header::pthread::e(Sys::rlct_kill(os_tid, sig as usize))
crate::header::pthread::e(unsafe { Sys::rlct_kill(os_tid, sig as usize) })
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_sigmask.html>.
@@ -191,7 +194,7 @@ pub unsafe extern "C" fn pthread_sigmask(
oldset: *mut sigset_t,
) -> c_int {
// On Linux and Redox, pthread_sigmask and sigprocmask are equivalent
if sigprocmask(how, set, oldset) == 0 {
if unsafe { sigprocmask(how, set, oldset) } == 0 {
0
} else {
//TODO: Fix race
@@ -212,7 +215,7 @@ pub unsafe extern "C" fn sigaction(
act: *const sigaction,
oact: *mut sigaction,
) -> c_int {
Sys::sigaction(sig, act.as_ref(), oact.as_mut())
Sys::sigaction(sig, unsafe { act.as_ref() }, unsafe { oact.as_mut() })
.map(|()| 0)
.or_minus_one_errno()
}
@@ -236,9 +239,11 @@ pub unsafe extern "C" fn sigaddset(set: *mut sigset_t, signo: c_int) -> c_int {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sigaltstack.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {
Sys::sigaltstack(ss.as_ref(), old_ss.as_mut())
.map(|()| 0)
.or_minus_one_errno()
unsafe {
Sys::sigaltstack(ss.as_ref(), old_ss.as_mut())
.map(|()| 0)
.or_minus_one_errno()
}
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sigdelset.html>.
@@ -260,7 +265,7 @@ pub unsafe extern "C" fn sigdelset(set: *mut sigset_t, signo: c_int) -> c_int {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sigemptyset.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sigemptyset(set: *mut sigset_t) -> c_int {
if let Some(set) = (set as *mut SigSet).as_mut() {
if let Some(set) = unsafe { (set as *mut SigSet).as_mut() } {
set.clear();
}
0
@@ -269,7 +274,7 @@ pub unsafe extern "C" fn sigemptyset(set: *mut sigset_t) -> c_int {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sigfillset.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sigfillset(set: *mut sigset_t) -> c_int {
if let Some(set) = (set as *mut SigSet).as_mut() {
if let Some(set) = unsafe { (set as *mut SigSet).as_mut() } {
set.fill(.., true);
}
0
@@ -285,10 +290,10 @@ pub unsafe extern "C" fn sighold(sig: c_int) -> c_int {
let mut pset = mem::MaybeUninit::<sigset_t>::uninit();
unsafe { sigemptyset(pset.as_mut_ptr()) };
let mut set = unsafe { pset.assume_init() };
if sigaddset(&mut set, sig) < 0 {
if unsafe { sigaddset(&mut set, sig) } < 0 {
return -1;
}
sigprocmask(SIG_BLOCK, &set, ptr::null_mut())
unsafe { sigprocmask(SIG_BLOCK, &set, ptr::null_mut()) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sighold.html>.
@@ -367,18 +372,18 @@ pub extern "C" fn signal(
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sigpause(sig: c_int) -> c_int {
let mut pset = mem::MaybeUninit::<sigset_t>::uninit();
sigprocmask(0, ptr::null_mut(), pset.as_mut_ptr());
let mut set = pset.assume_init();
if sigdelset(&mut set, sig) == -1 {
unsafe { sigprocmask(0, ptr::null_mut(), pset.as_mut_ptr()) };
let mut set = unsafe { pset.assume_init() };
if unsafe { sigdelset(&mut set, sig) } == -1 {
return -1;
}
sigsuspend(&set)
unsafe { sigsuspend(&set) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sigpending.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sigpending(set: *mut sigset_t) -> c_int {
(|| Sys::sigpending(set.as_mut().ok_or(Errno(EFAULT))?))()
(|| Sys::sigpending(unsafe { set.as_mut().ok_or(Errno(EFAULT)) }?))()
.map(|()| 0)
.or_minus_one_errno()
}
@@ -395,8 +400,8 @@ pub unsafe extern "C" fn sigprocmask(
oset: *mut sigset_t,
) -> c_int {
(|| {
let set = set.as_ref().map(|&block| block & !RLCT_SIGNAL_MASK);
let mut oset = oset.as_mut();
let set = unsafe { set.as_ref().map(|&block| block & !RLCT_SIGNAL_MASK) };
let mut oset = unsafe { oset.as_mut() };
Sys::sigprocmask(
how,
@@ -421,12 +426,12 @@ pub unsafe extern "C" fn sigprocmask(
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sigrelse(sig: c_int) -> c_int {
let mut pset = mem::MaybeUninit::<sigset_t>::uninit();
sigemptyset(pset.as_mut_ptr());
let mut set = pset.assume_init();
if sigaddset(&mut set, sig) < 0 {
unsafe { sigemptyset(pset.as_mut_ptr()) };
let mut set = unsafe { pset.assume_init() };
if unsafe { sigaddset(&mut set, sig) } < 0 {
return -1;
}
sigprocmask(SIG_UNBLOCK, &mut set, ptr::null_mut())
unsafe { sigprocmask(SIG_UNBLOCK, &mut set, ptr::null_mut()) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sighold.html>.
@@ -441,16 +446,16 @@ pub unsafe extern "C" fn sigset(
) -> Option<extern "C" fn(c_int)> {
let mut old_sa = mem::MaybeUninit::uninit();
let mut pset = mem::MaybeUninit::<sigset_t>::uninit();
let sig_hold: Option<extern "C" fn(c_int)> = mem::transmute(SIG_HOLD);
let sig_err: Option<extern "C" fn(c_int)> = mem::transmute(SIG_ERR);
sigemptyset(pset.as_mut_ptr());
let mut set = pset.assume_init();
if sigaddset(&mut set, sig) < 0 {
let sig_hold: Option<extern "C" fn(c_int)> = unsafe { mem::transmute(SIG_HOLD) };
let sig_err: Option<extern "C" fn(c_int)> = unsafe { mem::transmute(SIG_ERR) };
unsafe { sigemptyset(pset.as_mut_ptr()) };
let mut set = unsafe { pset.assume_init() };
if unsafe { sigaddset(&mut set, sig) } < 0 {
return sig_err;
} else {
if func == sig_hold {
if sigaction(sig, ptr::null_mut(), old_sa.as_mut_ptr()) < 0
|| sigprocmask(SIG_BLOCK, &mut set, &mut set) < 0
if unsafe { sigaction(sig, ptr::null_mut(), old_sa.as_mut_ptr()) } < 0
|| unsafe { sigprocmask(SIG_BLOCK, &mut set, &mut set) } < 0
{
mem::forget(old_sa);
return sig_err;
@@ -462,36 +467,36 @@ pub unsafe extern "C" fn sigset(
sa_restorer: None, // set by platform if applicable
sa_mask: sigset_t::default(),
};
sigemptyset(&mut sa.sa_mask);
if sigaction(sig, &sa, old_sa.as_mut_ptr()) < 0
|| sigprocmask(SIG_UNBLOCK, &mut set, &mut set) < 0
unsafe { sigemptyset(&mut sa.sa_mask) };
if unsafe { sigaction(sig, &sa, old_sa.as_mut_ptr()) } < 0
|| unsafe { sigprocmask(SIG_UNBLOCK, &mut set, &mut set) } < 0
{
mem::forget(old_sa);
return sig_err;
}
}
}
if sigismember(&mut set, sig) == 1 {
if unsafe { sigismember(&mut set, sig) } == 1 {
return sig_hold;
}
old_sa.assume_init().sa_handler
unsafe { old_sa.assume_init().sa_handler }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sigsuspend.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sigsuspend(sigmask: *const sigset_t) -> c_int {
Err(Sys::sigsuspend(&*sigmask)).or_minus_one_errno()
Err(Sys::sigsuspend(unsafe { &*sigmask })).or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sigwait.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int {
let mut pinfo = mem::MaybeUninit::<siginfo_t>::uninit();
if sigtimedwait(set, pinfo.as_mut_ptr(), ptr::null_mut()) < 0 {
if unsafe { sigtimedwait(set, pinfo.as_mut_ptr(), ptr::null_mut()) } < 0 {
return -1;
}
let info = pinfo.assume_init();
(*sig) = info.si_signo;
let info = unsafe { pinfo.assume_init() };
unsafe { (*sig) = info.si_signo };
0
}
@@ -505,15 +510,17 @@ pub unsafe extern "C" fn sigtimedwait(
// to differentiate between sigtimedwait and sigwaitinfo internally
tp: *const timespec,
) -> c_int {
Sys::sigtimedwait(&*set, sig.as_mut(), tp.as_ref())
.map(|()| 0)
.or_minus_one_errno()
Sys::sigtimedwait(unsafe { &*set }, unsafe { sig.as_mut() }, unsafe {
tp.as_ref()
})
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sigwaitinfo.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sigwaitinfo(set: *const sigset_t, sig: *mut siginfo_t) -> c_int {
sigtimedwait(set, sig, core::ptr::null())
unsafe { sigtimedwait(set, sig, core::ptr::null()) }
}
pub(crate) const SIGNAL_STRINGS: [&str; 32] = [
@@ -559,15 +566,17 @@ pub unsafe extern "C" fn psignal(sig: c_int, prefix: *const c_char) {
.and_then(|idx| SIGNAL_STRINGS.get(idx))
.unwrap_or(&SIGNAL_STRINGS[0]);
let description = &c_description[..c_description.len() - 1];
let prefix = CStr::from_ptr(prefix).to_string_lossy();
let prefix = unsafe { CStr::from_ptr(prefix).to_string_lossy() };
// TODO: stack vec or print directly?
let string = alloc::format!("{prefix}:{description}\n");
// TODO: better internal libc API?
let _ = unistd::write(
unistd::STDERR_FILENO,
string.as_bytes().as_ptr().cast(),
string.as_bytes().len(),
);
let _ = unsafe {
unistd::write(
unistd::STDERR_FILENO,
string.as_bytes().as_ptr().cast(),
string.as_bytes().len(),
)
};
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/psiginfo.html>.
@@ -582,9 +591,9 @@ pub unsafe extern "C" fn psiginfo(info: *const siginfo_t, prefix: *const c_char)
si_addr,
si_status,
si_value,
} = &*info;
let sival_ptr = si_value.sival_ptr;
let prefix = CStr::from_ptr(prefix).to_string_lossy();
} = unsafe { &*info };
let sival_ptr = unsafe { si_value.sival_ptr };
let prefix = unsafe { CStr::from_ptr(prefix).to_string_lossy() };
// TODO: stack vec or print directly?
let string = alloc::format!(
"{prefix}:siginfo_t {{
@@ -600,11 +609,13 @@ pub unsafe extern "C" fn psiginfo(info: *const siginfo_t, prefix: *const c_char)
"
);
// TODO: better internal libc API?
let _ = unistd::write(
unistd::STDERR_FILENO,
string.as_bytes().as_ptr().cast(),
string.as_bytes().len(),
);
let _ = unsafe {
unistd::write(
unistd::STDERR_FILENO,
string.as_bytes().as_ptr().cast(),
string.as_bytes().len(),
)
};
}
#[unsafe(no_mangle)]