diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 4a8e0a675da2111c911325c1eb6058e5a0aa2e24..e041bfd3d720505eb768d2b766d8e2f6ff3ed69f 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -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() diff --git a/src/header/signal/mod.rs b/src/header/signal/mod.rs index 05462424a27eaf176713e190fc3e96fa66586cd6..930e66b6e7db6436c7f0f68033f3ebacf84d43c1 100644 --- a/src/header/signal/mod.rs +++ b/src/header/signal/mod.rs @@ -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() } diff --git a/src/platform/linux/signal.rs b/src/platform/linux/signal.rs index bc438a6853e1d725caf799de834646d5ff9a9bb1..f772988a025c476f38d2ae89921cf7e856377802 100644 --- a/src/platform/linux/signal.rs +++ b/src/platform/linux/signal.rs @@ -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 )) diff --git a/src/platform/pal/signal.rs b/src/platform/pal/signal.rs index 99699f68ea928635be63cd3819c36e8cdc4c98f8..4d2dbb6ff393b7319527645b151aebad5e46cbd2 100644 --- a/src/platform/pal/signal.rs +++ b/src/platform/pal/signal.rs @@ -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>; } diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs index 189662cbc9793c1a8478547b6945777ce2e6dd0b..a5f0c105091fcc8707f74bef460e70e0894bac9a 100644 --- a/src/platform/redox/signal.rs +++ b/src/platform/redox/signal.rs @@ -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(()) } } diff --git a/tests/sigaction.c b/tests/sigaction.c index b7ad9c12c6a400ab392f3e23bf87822575d7d4f7..b332f3902d1e7ea3f57a11490e2919e35425f854 100644 --- a/tests/sigaction.c +++ b/tests/sigaction.c @@ -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) { diff --git a/tests/sigqueue.c b/tests/sigqueue.c index 7c67fb2fb0675254af7a52cac42aff186d1ff342..78e4eeffd5ea55f44dba6d3c31788ed7c0f528a6 100644 --- a/tests/sigqueue.c +++ b/tests/sigqueue.c @@ -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); }