Handle signal mask in epoll_pwait

This commit is contained in:
Jeremy Soller
2026-01-09 11:46:54 -07:00
parent c433f39788
commit d8f47cf5fb
2 changed files with 52 additions and 7 deletions
+33
View File
@@ -783,6 +783,38 @@ pub fn await_signal_async(inner_allowset: u64) -> Result<Unreachable> {
res?;
unreachable!()
}
/// Run a callback with the specified signal mask, atomically
pub fn callback_or_signal_async<T, F: FnOnce() -> Result<T>>(inner_allowset: u64, callback: F) -> Result<T> {
let _guard = tmp_disable_signals();
let control = &unsafe { Tcb::current().unwrap() }.os_specific.control;
let old_allowset = get_allowset_raw(&control.word);
let pending = set_allowset_raw(&control.word, old_allowset, inner_allowset);
let res = if pending == 0 {
// Run callback if no pending signals
callback()
} else {
// If pending signals, pretend callback returned EINTR
Err(Error::new(EINTR))
};
if let Err(err) = &res {
if err.errno == EINTR {
// Run trampoline if EINTR returned
unsafe {
manually_enter_trampoline();
}
}
}
// POSIX says it shall restore the mask to what it was prior to the call, which is interpreted
// as allowing any changes to sigprocmask inside the signal handler, to be discarded.
set_allowset_raw(&control.word, inner_allowset, old_allowset);
res
}
/*#[unsafe(no_mangle)]
pub extern "C" fn __redox_rt_debug_sigctl() {
let tcb = &RtTcb::current().control;
@@ -830,6 +862,7 @@ pub fn await_signal_sync(inner_allowset: u64, timeout: Option<&TimeSpec>) -> Res
// Normally ETIMEDOUT but not for sigtimedwait.
.ok_or(Error::new(EAGAIN))
}
fn try_claim_multiple(
mut proc_pending: u64,
mut thread_pending: u64,
+19 -7
View File
@@ -96,7 +96,7 @@ impl PalEpoll for Sys {
events: *mut epoll_event,
maxevents: c_int,
timeout: c_int,
_sigset: *const sigset_t,
sigset: *const sigset_t,
) -> Result<usize, Errno> {
// TODO: sigset
assert_eq!(mem::size_of::<epoll_event>(), mem::size_of::<Event>());
@@ -131,12 +131,24 @@ impl PalEpoll for Sys {
None
};
let bytes_read = Sys::read(epfd, unsafe {
slice::from_raw_parts_mut(
events as *mut u8,
maxevents as usize * mem::size_of::<syscall::Event>(),
)
})?;
let callback = || {
let res = redox_rt::sys::posix_read(epfd as usize, unsafe {
slice::from_raw_parts_mut(
events as *mut u8,
maxevents as usize * mem::size_of::<syscall::Event>(),
)
});
res
};
let bytes_read = if sigset.is_null() {
callback()
} else {
// Allowset is inverse of sigset mask
let allowset = !*sigset;
redox_rt::signal::callback_or_signal_async(allowset, callback)
}?;
let read = bytes_read as usize / mem::size_of::<syscall::Event>();
let mut count = 0;