Add sigtimedwait to test, and various fixes.
This commit is contained in:
@@ -727,13 +727,15 @@ fn try_claim_multiple(
|
||||
) -> Option<SiginfoAbi> {
|
||||
while (proc_pending | thread_pending) & allowset != 0 {
|
||||
let sig_idx = ((proc_pending | thread_pending) & allowset).trailing_zeros();
|
||||
if thread_pending & (1 << sig_idx) != 0
|
||||
if thread_pending & allowset & (1 << sig_idx) != 0
|
||||
&& let Some(res) = try_claim_single(sig_idx, Some(control))
|
||||
{
|
||||
return Some(res);
|
||||
}
|
||||
thread_pending &= !(1 << sig_idx);
|
||||
if let Some(res) = try_claim_single(sig_idx, None) {
|
||||
if proc_pending & allowset & (1 << sig_idx) != 0
|
||||
&& let Some(res) = try_claim_single(sig_idx, None)
|
||||
{
|
||||
return Some(res);
|
||||
}
|
||||
proc_pending &= !(1 << sig_idx);
|
||||
@@ -741,7 +743,7 @@ fn try_claim_multiple(
|
||||
None
|
||||
}
|
||||
fn try_claim_single(sig_idx: u32, thread_control: Option<&Sigcontrol>) -> Option<SiginfoAbi> {
|
||||
let sig_group = sig_idx / 1;
|
||||
let sig_group = sig_idx / 32;
|
||||
|
||||
if sig_group == 1 && thread_control.is_none() {
|
||||
// Queued (realtime) signal
|
||||
@@ -749,8 +751,8 @@ fn try_claim_single(sig_idx: u32, thread_control: Option<&Sigcontrol>) -> Option
|
||||
let rt_inf = unsafe {
|
||||
syscall::syscall2(
|
||||
syscall::SYS_SIGDEQUEUE,
|
||||
sig_idx as usize,
|
||||
ret.as_mut_ptr() as usize,
|
||||
sig_idx as usize - 32,
|
||||
)
|
||||
.ok()?;
|
||||
ret.assume_init()
|
||||
|
||||
@@ -142,7 +142,9 @@ pub unsafe extern "C" fn sigaction(
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sigaddset(set: *mut sigset_t, signo: c_int) -> c_int {
|
||||
if signo <= 0 || signo as usize > NSIG {
|
||||
if signo <= 0 || signo as usize > NSIG.max(SIGRTMAX)
|
||||
/* TODO */
|
||||
{
|
||||
platform::ERRNO.set(errno::EINVAL);
|
||||
return -1;
|
||||
}
|
||||
@@ -162,7 +164,9 @@ pub unsafe extern "C" fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sigdelset(set: *mut sigset_t, signo: c_int) -> c_int {
|
||||
if signo <= 0 || signo as usize > NSIG {
|
||||
if signo <= 0 || signo as usize > NSIG.max(SIGRTMAX)
|
||||
/* TODO */
|
||||
{
|
||||
platform::ERRNO.set(errno::EINVAL);
|
||||
return -1;
|
||||
}
|
||||
@@ -379,7 +383,7 @@ pub unsafe extern "C" fn sigtimedwait(
|
||||
sig: *mut siginfo, // https://github.com/mozilla/cbindgen/issues/621
|
||||
tp: *const timespec,
|
||||
) -> c_int {
|
||||
Sys::sigtimedwait(&*set, &mut *sig, &*tp)
|
||||
Sys::sigtimedwait(&*set, sig.as_mut(), &*tp)
|
||||
.map(|()| 0)
|
||||
.or_minus_one_errno()
|
||||
}
|
||||
|
||||
@@ -155,18 +155,23 @@ impl PalSignal for Sys {
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
fn sigsuspend(set: &sigset_t) -> Errno {
|
||||
fn sigsuspend(mask: &sigset_t) -> Errno {
|
||||
unsafe {
|
||||
e_raw(syscall!(RT_SIGSUSPEND, set as *const sigset_t, NSIG / 8)).expect_err("must fail")
|
||||
e_raw(syscall!(RT_SIGSUSPEND, mask as *const sigset_t, NSIG / 8))
|
||||
.expect_err("must fail")
|
||||
}
|
||||
}
|
||||
|
||||
fn sigtimedwait(set: &sigset_t, sig: &mut siginfo_t, tp: ×pec) -> Result<(), Errno> {
|
||||
fn sigtimedwait(
|
||||
set: &sigset_t,
|
||||
sig: Option<&mut siginfo_t>,
|
||||
tp: ×pec,
|
||||
) -> Result<(), Errno> {
|
||||
unsafe {
|
||||
e_raw(syscall!(
|
||||
RT_SIGTIMEDWAIT,
|
||||
set as *const _,
|
||||
sig as *mut _,
|
||||
sig.map_or_else(core::ptr::null_mut, |s| s as *mut _) as usize,
|
||||
tp as *const _,
|
||||
NSIG / 8
|
||||
))
|
||||
|
||||
@@ -39,5 +39,9 @@ pub trait PalSignal: Pal {
|
||||
|
||||
fn sigsuspend(mask: &sigset_t) -> Errno; // always fails
|
||||
|
||||
fn sigtimedwait(set: &sigset_t, sig: &mut siginfo_t, tp: ×pec) -> Result<(), Errno>;
|
||||
fn sigtimedwait(
|
||||
set: &sigset_t,
|
||||
sig: Option<&mut siginfo_t>,
|
||||
tp: ×pec,
|
||||
) -> Result<(), Errno>;
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ impl PalSignal for Sys {
|
||||
|
||||
fn sigtimedwait(
|
||||
set: &sigset_t,
|
||||
info_out: &mut siginfo_t,
|
||||
info_out: Option<&mut siginfo_t>,
|
||||
timeout: ×pec,
|
||||
) -> Result<(), Errno> {
|
||||
// TODO: deadline-based API
|
||||
@@ -281,7 +281,10 @@ impl PalSignal for Sys {
|
||||
tv_sec: timeout.tv_sec,
|
||||
tv_nsec: timeout.tv_nsec as _,
|
||||
};
|
||||
*info_out = redox_rt::signal::await_signal_sync(*set, &timeout)?.into();
|
||||
let info = redox_rt::signal::await_signal_sync(*set, &timeout)?.into();
|
||||
if let Some(out) = info_out {
|
||||
*out = info;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +23,19 @@ void handler2(int sig, siginfo_t *info, void *context_raw) {
|
||||
|
||||
assert(info != NULL);
|
||||
assert(info->si_signo == SIGUSR1);
|
||||
#ifndef __linux
|
||||
// TODO: SI_TKILL?
|
||||
assert(info->si_code == SI_USER);
|
||||
assert(info->si_pid == getpid());
|
||||
assert(info->si_uid == getuid());
|
||||
#endif
|
||||
|
||||
ucontext_t *context = context_raw;
|
||||
assert(context != NULL);
|
||||
#ifndef __linux__ // TODO
|
||||
assert(memcmp(&context->uc_sigmask, &the_set, sizeof(sigset_t)));
|
||||
assert(context->uc_link == NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
+32
-17
@@ -10,20 +10,24 @@
|
||||
|
||||
#define THE_SIG SIGRTMIN
|
||||
|
||||
volatile sig_atomic_t num = 1;
|
||||
volatile sig_atomic_t num = 0;
|
||||
|
||||
int parent;
|
||||
|
||||
void action(int sig, siginfo_t *info, void *context) {
|
||||
(void)context;
|
||||
void validate(int sig, const siginfo_t *info) {
|
||||
assert(sig == THE_SIG);
|
||||
assert(info != NULL);
|
||||
assert(context != NULL);
|
||||
assert(info->si_signo == THE_SIG);
|
||||
assert(info->si_value.sival_int == num);
|
||||
assert(info->si_code == SI_QUEUE);
|
||||
assert(info->si_pid == parent);
|
||||
}
|
||||
|
||||
void action(int sig, siginfo_t *info, void *context) {
|
||||
num++;
|
||||
(void)context;
|
||||
assert(context != NULL);
|
||||
validate(sig, info);
|
||||
write(1, "action\n", 7);
|
||||
}
|
||||
|
||||
@@ -42,22 +46,27 @@ int main(void) {
|
||||
status = close(fds[child == 0 ? 0 : 1]);
|
||||
ERROR_IF(close, status, == -1);
|
||||
|
||||
sigset_t set;
|
||||
status = sigfillset(&set);
|
||||
sigset_t set, mask;
|
||||
status = sigfillset(&mask);
|
||||
ERROR_IF(sigfillset, status, == -1);
|
||||
status = sigdelset(&set, SIGSEGV);
|
||||
status = sigdelset(&mask, SIGSEGV);
|
||||
ERROR_IF(sigdelset, status, == -1);
|
||||
status = sigdelset(&set, SIGBUS);
|
||||
status = sigdelset(&mask, SIGBUS);
|
||||
ERROR_IF(sigdelset, status, == -1);
|
||||
status = sigdelset(&set, SIGILL);
|
||||
status = sigdelset(&mask, SIGILL);
|
||||
ERROR_IF(sigdelset, status, == -1);
|
||||
status = sigdelset(&set, SIGFPE);
|
||||
status = sigdelset(&mask, SIGFPE);
|
||||
ERROR_IF(sigdelset, status, == -1);
|
||||
status = sigdelset(&set, SIGINT);
|
||||
status = sigdelset(&mask, SIGINT);
|
||||
ERROR_IF(sigdelset, status, == -1);
|
||||
status = sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
status = sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||
ERROR_IF(sigprocmask, status, == -1);
|
||||
|
||||
status = sigemptyset(&set);
|
||||
ERROR_IF(sigemptyset, status, == -1);
|
||||
status = sigaddset(&set, THE_SIG);
|
||||
ERROR_IF(sigaddset, status, == -1);
|
||||
|
||||
struct sigaction sa;
|
||||
memcpy(&sa.sa_mask, &set, sizeof (sigset_t));
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
@@ -67,14 +76,20 @@ int main(void) {
|
||||
ERROR_IF(sigaction, status, == -1);
|
||||
|
||||
if (child == 0) {
|
||||
status = sigemptyset(&set);
|
||||
ERROR_IF(sigemptyset, status, == -1);
|
||||
while (num != 32) {
|
||||
}
|
||||
assert(num == 0);
|
||||
siginfo_t info;
|
||||
struct timespec t = (struct timespec){ .tv_sec = 1, .tv_nsec = 0 };
|
||||
status = sigtimedwait(&set, &info, &t);
|
||||
ERROR_IF(sigtimedwait, status, == -1);
|
||||
validate(THE_SIG, &info);
|
||||
assert(num == 0); // ensure no signal handler ran
|
||||
|
||||
while (num < 31) {}
|
||||
|
||||
status = write(fds[1], "A", 1);
|
||||
ERROR_IF(write, status, == -1);
|
||||
} else {
|
||||
for (int n = 1; n <= 32; n++) {
|
||||
for (int n = 0; n <= 31; n++) {
|
||||
status = sigqueue(child, THE_SIG, (union sigval){ .sival_int = n });
|
||||
ERROR_IF(sigqueue, status, == -1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user