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: &timespec) -> Result<(), Errno> {
+    fn sigtimedwait(
+        set: &sigset_t,
+        sig: Option<&mut siginfo_t>,
+        tp: &timespec,
+    ) -> 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: &timespec) -> Result<(), Errno>;
+    fn sigtimedwait(
+        set: &sigset_t,
+        sig: Option<&mut siginfo_t>,
+        tp: &timespec,
+    ) -> 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: &timespec,
     ) -> 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);
     }