diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 026ba119b8..495fa472e2 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -783,6 +783,38 @@ pub fn await_signal_async(inner_allowset: u64) -> Result { res?; unreachable!() } + +/// Run a callback with the specified signal mask, atomically +pub fn callback_or_signal_async Result>(inner_allowset: u64, callback: F) -> Result { + 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, diff --git a/src/platform/redox/epoll.rs b/src/platform/redox/epoll.rs index 14e8a6853f..e89577bcab 100644 --- a/src/platform/redox/epoll.rs +++ b/src/platform/redox/epoll.rs @@ -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 { // TODO: sigset assert_eq!(mem::size_of::(), mem::size_of::()); @@ -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::(), - ) - })?; + 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::(), + ) + }); + 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::(); let mut count = 0;