Merge branch 'fix-ppoll' into 'master'
Handle signal mask in epoll_pwait See merge request redox-os/relibc!879
This commit is contained in:
@@ -783,6 +783,34 @@ 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);
|
||||
set_allowset_raw(&control.word, old_allowset, inner_allowset);
|
||||
let res = callback();
|
||||
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 +858,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,
|
||||
|
||||
+20
-6
@@ -11,6 +11,7 @@ use crate::{
|
||||
error::ResultExt,
|
||||
fs::File,
|
||||
header::{
|
||||
errno::EBADF,
|
||||
signal::sigset_t,
|
||||
sys_epoll::{
|
||||
EPOLL_CLOEXEC, EPOLL_CTL_ADD, EPOLLERR, EPOLLHUP, EPOLLIN, EPOLLNVAL, EPOLLOUT,
|
||||
@@ -19,7 +20,10 @@ use crate::{
|
||||
},
|
||||
time::timespec,
|
||||
},
|
||||
platform::types::{c_int, c_short, c_ulong},
|
||||
platform::{
|
||||
self,
|
||||
types::{c_int, c_short, c_ulong},
|
||||
},
|
||||
};
|
||||
|
||||
pub const POLLIN: c_short = 0x001;
|
||||
@@ -65,12 +69,14 @@ pub fn poll_epoll(fds: &mut [pollfd], timeout: c_int, sigmask: *const sigset_t)
|
||||
File::new(epfd)
|
||||
};
|
||||
|
||||
let mut closed = 0;
|
||||
for i in 0..fds.len() {
|
||||
let mut pfd = &mut fds[i];
|
||||
|
||||
// Ignore the entry with negative fd, set the revents to 0
|
||||
pfd.revents = 0;
|
||||
|
||||
// Ignore the entry with negative fd
|
||||
if pfd.fd < 0 {
|
||||
pfd.revents = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -86,13 +92,21 @@ pub fn poll_epoll(fds: &mut [pollfd], timeout: c_int, sigmask: *const sigset_t)
|
||||
}
|
||||
}
|
||||
|
||||
pfd.revents = 0;
|
||||
|
||||
if unsafe { epoll_ctl(*ep, EPOLL_CTL_ADD, pfd.fd, &mut event) } < 0 {
|
||||
return -1;
|
||||
if platform::ERRNO.get() == EBADF {
|
||||
pfd.revents |= POLLNVAL;
|
||||
closed += 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Early exit if there are fds, and all are closed (revents = POLLNVAL)
|
||||
if closed > 0 && closed == fds.len() {
|
||||
return closed as i32;
|
||||
}
|
||||
|
||||
let mut events: [epoll_event; 32] = unsafe { mem::zeroed() };
|
||||
let res = unsafe {
|
||||
epoll_pwait(
|
||||
|
||||
@@ -96,9 +96,8 @@ 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>());
|
||||
|
||||
if maxevents <= 0 {
|
||||
@@ -131,12 +130,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 = syscall::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