Handle signal mask in epoll_pwait
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user