diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs
index c1a11cd278e89760d09d9adef203c81e6c163372..cc1fa646556bdcfca589ea53cb2921276b12fb48 100644
--- a/redox-rt/src/arch/x86_64.rs
+++ b/redox-rt/src/arch/x86_64.rs
@@ -16,6 +16,7 @@ pub struct SigArea {
     altstack_top: usize,
     altstack_bottom: usize,
     tmp: usize,
+    pub onstack: u64,
     pub disable_signals_depth: u64,
 }
 
@@ -128,18 +129,41 @@ asmfunction!(__relibc_internal_rlct_clone_ret -> usize: ["
 "] <= []);
 
 asmfunction!(__relibc_internal_sigentry: ["
-    // Get offset to TCB
-    mov rax, gs:[0]
+    // First, select signal, always pick first available bit
+
+    // Read first signal word
+    mov rdx, fs:[{tcb_sc_off} + {sc_word}]
+    mov rcx, rdx
+    shr rcx, 32
+    and edx, ecx
+    bsf edx, edx
+    jnz 2f
+
+    // Read second signal word
+    mov rdx, fs:[{tcb_sc_off} + {sc_word} + 8]
+    mov rcx, rdx
+    shr rcx, 32
+    and edx, ecx
+    bsf edx, edx
+    jnz 4f
+    add edx, 32
+2:
+    // By now we have selected a signal, stored in edx (6-bit). We now need to choose whether or
+    // not to switch to the alternate signal stack. If SA_ONSTACK is clear for this signal, then
+    // skip the sigaltstack logic.
+    bt fs:[{tcb_sa_off} + {sa_onstack}], edx
+    jc 3f
 
     // If current RSP is above altstack region, switch to altstack
-    mov rdx, [rax + {tcb_sa_off} + {sa_altstack_top}]
+    mov rdx, fs:[{tcb_sa_off} + {sa_altstack_top}]
     cmp rdx, rsp
     cmova rsp, rdx
 
     // If current RSP is below altstack region, also switch to altstack
-    mov rdx, [rax + {tcb_sa_off} + {sa_altstack_bottom}]
-    cmp rdx, rax
+    mov rdx, fs:[{tcb_sa_off} + {sa_altstack_bottom}]
+    cmp rdx, rsp
     cmovbe rsp, rdx
+3:
 
     // Otherwise, the altstack is already active. The sigaltstack being disabled, is equivalent
     // to setting 'top' to usize::MAX and 'bottom' to 0.
@@ -147,16 +171,16 @@ asmfunction!(__relibc_internal_sigentry: ["
     // Now that we have a stack, we can finally start initializing the signal stack!
 
     push 0 // SS
-    push [rax + {tcb_sc_off} + {sc_saved_rsp}]
-    push [rax + {tcb_sc_off} + {sc_saved_rflags}]
+    push fs:[{tcb_sc_off} + {sc_saved_rsp}]
+    push fs:[{tcb_sc_off} + {sc_saved_rflags}]
     push 0 // CS
-    push [rax + {tcb_sc_off} + {sc_saved_rip}]
+    push fs:[{tcb_sc_off} + {sc_saved_rip}]
 
     push rdi
     push rsi
-    push [rax + {tcb_sc_off} + {sc_saved_rdx}]
+    push fs:[{tcb_sc_off} + {sc_saved_rdx}]
     push rcx
-    push [rax + {tcb_sc_off} + {sc_saved_rax}]
+    push fs:[{tcb_sc_off} + {sc_saved_rax}]
     push r8
     push r9
     push r10
@@ -168,12 +192,14 @@ asmfunction!(__relibc_internal_sigentry: ["
     push r14
     push r15
 
-    sub rsp, 4096 + 32
+    push rdx // selected signal
+
+    sub rsp, 4096 + 24
 
     cld
     mov rdi, rsp
     xor eax, eax
-    mov ecx, 4096 + 32
+    mov ecx, 4096 + 24
     rep stosb
 
     // TODO: self-modifying?
@@ -191,7 +217,7 @@ asmfunction!(__relibc_internal_sigentry: ["
     mov edx, eax
     xrstor [rsp]
 
-    add rsp, 4096 + 32
+    add rsp, 4096 + 24
 2:
     pop r15
     pop r14
@@ -209,11 +235,11 @@ asmfunction!(__relibc_internal_sigentry: ["
     pop rsi
     pop rdi
 
-    pop qword ptr gs:[{tcb_sa_off} + {sa_tmp}]
+    pop qword ptr fs:[{tcb_sa_off} + {sa_tmp}]
     add rsp, 8
     popfq
     pop rsp
-    jmp qword ptr gs:[{tcb_sa_off} + {sa_tmp}]
+    jmp qword ptr fs:[{tcb_sa_off} + {sa_tmp}]
 3:
     fxsave64 [rsp]
 
@@ -222,16 +248,20 @@ asmfunction!(__relibc_internal_sigentry: ["
 
     fxrstor64 [rsp]
     jmp 2b
+4:
+    // Spurious signal
 "] <= [
     inner = sym inner_c,
     sa_tmp = const offset_of!(SigArea, tmp),
     sa_altstack_top = const offset_of!(SigArea, altstack_top),
     sa_altstack_bottom = const offset_of!(SigArea, altstack_bottom),
+    sa_onstack = const offset_of!(SigArea, onstack),
     sc_saved_rax = const offset_of!(Sigcontrol, saved_scratch_a),
     sc_saved_rdx = const offset_of!(Sigcontrol, saved_scratch_b),
     sc_saved_rflags = const offset_of!(Sigcontrol, saved_flags),
     sc_saved_rip = const offset_of!(Sigcontrol, saved_ip),
     sc_saved_rsp = const offset_of!(Sigcontrol, saved_sp),
+    sc_word = const offset_of!(Sigcontrol, word),
     tcb_sa_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, arch),
     tcb_sc_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, control),
     supports_xsave = sym SUPPORTS_XSAVE,
diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs
index 24ff85f5a1ad0fc1cb01d82e66a2b0b57e3e8f1e..e45cfa4c4c84c30699de8ad7eeacfae5f348663c 100644
--- a/redox-rt/src/signal.rs
+++ b/redox-rt/src/signal.rs
@@ -2,7 +2,7 @@ use core::cell::Cell;
 use core::ffi::c_int;
 use core::sync::atomic::{AtomicU64, Ordering};
 
-use syscall::{Error, IntRegisters, Result, SetSighandlerData, SigProcControl, Sigcontrol, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGW0_TSTP_IS_STOP_BIT, SIGW0_TTIN_IS_STOP_BIT, SIGW0_TTOU_IS_STOP_BIT, SIGWINCH};
+use syscall::{Error, IntRegisters, Result, SetSighandlerData, SigProcControl, Sigcontrol, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGW0_NOCLDSTOP_BIT, SIGW0_TSTP_IS_STOP_BIT, SIGW0_TTIN_IS_STOP_BIT, SIGW0_TTOU_IS_STOP_BIT, SIGWINCH};
 
 use crate::{arch::*, Tcb};
 use crate::sync::Mutex;
@@ -104,16 +104,24 @@ fn modify_sigmask(old: Option<&mut u64>, op: Option<impl FnMut(u32, bool) -> u32
     Ok(())
 }
 
-#[derive(Clone, Copy)]
-pub enum Sigaction {
+#[derive(Clone, Copy, Default)]
+pub enum SigactionKind {
+    #[default]
     Default,
+
     Ignore,
     Handled {
         handler: SignalHandler,
-        mask: u64,
-        flags: SigactionFlags,
     },
 }
+
+#[derive(Clone, Copy, Default)]
+pub struct Sigaction {
+    pub kind: SigactionKind,
+    pub mask: u64,
+    pub flags: SigactionFlags,
+}
+
 pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction>) -> Result<()> {
     if matches!(usize::from(signal), 0 | 32 | SIGKILL | SIGSTOP | 65..) {
         return Err(Error::new(EINVAL));
@@ -125,39 +133,59 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction
     let old_ignmask = IGNMASK.load(Ordering::Relaxed);
 
     if let Some(old) = old {
+        // TODO
     }
 
     let Some(new) = new else {
         return Ok(());
     };
 
-    match (usize::from(signal), new) {
-        (_, Sigaction::Ignore) | (SIGCHLD | SIGURG | SIGWINCH, Sigaction::Default) => {
+    let sig_group = usize::from(signal) / 32;
+    let sig_bit32 = 1 << ((signal - 1) % 32);
+
+    match (usize::from(signal), new.kind) {
+        (_, SigactionKind::Ignore) | (SIGURG | SIGWINCH, SigactionKind::Default) => {
             IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed);
 
             // mark the signal as masked
-            ctl.word[usize::from(signal) / 32].fetch_or(1 << ((signal - 1) % 32), Ordering::Relaxed);
+            ctl.word[sig_group].fetch_or(sig_bit32, Ordering::Relaxed);
 
             // POSIX specifies that pending signals shall be discarded if set to SIG_IGN by
             // sigaction.
             // TODO: handle tmp_disable_signals
         }
         // TODO: Handle pending signals before these flags are set.
-        (SIGTSTP, Sigaction::Default) => {
+        (SIGTSTP, SigactionKind::Default) => {
             PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TSTP_IS_STOP_BIT, Ordering::SeqCst);
         }
-        (SIGTTIN, Sigaction::Default) => {
+        (SIGTTIN, SigactionKind::Default) => {
             PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTIN_IS_STOP_BIT, Ordering::SeqCst);
         }
-        (SIGTTOU, Sigaction::Default) => {
+        (SIGTTOU, SigactionKind::Default) => {
             PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTOU_IS_STOP_BIT, Ordering::SeqCst);
         }
+        (SIGCHLD, SigactionKind::Default) => {
+            if new.flags.contains(SigactionFlags::NOCLDSTOP) {
+                PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_NOCLDSTOP_BIT, Ordering::SeqCst);
+            } else {
+                PROC_CONTROL_STRUCT.word[0].fetch_and(!SIGW0_NOCLDSTOP_BIT, Ordering::SeqCst);
+            }
+            IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed);
+
+            // mark the signal as masked
+            ctl.word[sig_group].fetch_or(sig_bit32, Ordering::Relaxed);
+        }
+
+        (_, SigactionKind::Default) => {
+            IGNMASK.store(old_ignmask & !sig_bit(signal.into()), Ordering::Relaxed);
 
-        (_, Sigaction::Default) => (),
-        (_, Sigaction::Handled { .. }) => (),
+            // TODO: update mask
+            //ctl.word[usize::from(signal)].fetch_or();
+        },
+        (_, SigactionKind::Handled { .. }) => (),
     }
 
-    todo!()
+    Ok(())
 }
 
 fn current_sigctl() -> &'static Sigcontrol {
@@ -192,7 +220,7 @@ impl Drop for TmpDisableSignalsGuard {
 
 bitflags::bitflags! {
     // Some flags are ignored by the rt, but they match relibc's 1:1 to simplify conversion.
-    #[derive(Clone, Copy)]
+    #[derive(Clone, Copy, Default)]
     pub struct SigactionFlags: u32 {
         const NOCLDSTOP = 1;
         const NOCLDWAIT = 2;
@@ -226,7 +254,7 @@ struct TheDefault {
     ignmask: u64,
 }
 
-static SIGACTIONS: Mutex<[Sigaction; 64]> = Mutex::new([Sigaction::Default; 64]);
+static SIGACTIONS: Mutex<[Sigaction; 64]> = Mutex::new([Sigaction { flags: SigactionFlags::empty(), mask: 0, kind: SigactionKind::Default }; 64]);
 static IGNMASK: AtomicU64 = AtomicU64::new(sig_bit(SIGCHLD) | sig_bit(SIGURG) | sig_bit(SIGWINCH));
 
 static PROC_CONTROL_STRUCT: SigProcControl = SigProcControl {
diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs
index 625ac730c0a3e4f1aa1602c71a060a9c6f3952dc..59d0390eda9f536c88f6a01effb118b83451518b 100644
--- a/src/platform/redox/signal.rs
+++ b/src/platform/redox/signal.rs
@@ -1,5 +1,5 @@
 use core::mem;
-use redox_rt::signal::{Sigaction, SigactionFlags, SignalHandler};
+use redox_rt::signal::{Sigaction, SigactionFlags, SigactionKind, SignalHandler};
 use syscall::{self, Result};
 
 use super::{
@@ -111,49 +111,53 @@ impl PalSignal for Sys {
         let new_action = c_act.map(|c_act| {
             let handler = c_act.sa_handler.map_or(0, |f| f as usize);
 
-            if handler == SIG_DFL {
-                Sigaction::Default
+            let kind = if handler == SIG_DFL {
+                SigactionKind::Default
             } else if handler == SIG_IGN {
-                Sigaction::Ignore
+                SigactionKind::Ignore
             } else {
-                Sigaction::Handled {
+                SigactionKind::Handled {
                     handler: if c_act.sa_flags & crate::header::signal::SA_SIGINFO as u64 != 0 {
                         SignalHandler { sigaction: unsafe { core::mem::transmute(c_act.sa_handler) } }
                     } else {
                         SignalHandler { handler: c_act.sa_handler }
                     },
-                    mask: c_act.sa_mask,
-                    flags: SigactionFlags::from_bits_retain(c_act.sa_flags as u32),
                 }
+            };
+
+            Sigaction {
+                kind,
+                mask: c_act.sa_mask,
+                flags: SigactionFlags::from_bits_retain(c_act.sa_flags as u32),
             }
         });
-        let mut old_action = c_oact.as_ref().map(|_| Sigaction::Default);
+        let mut old_action = c_oact.as_ref().map(|_| Sigaction::default());
 
         redox_rt::signal::sigaction(sig, new_action.as_ref(), old_action.as_mut())?;
 
         if let (Some(c_oact), Some(old_action)) = (c_oact, old_action) {
-            *c_oact = match old_action {
-                Sigaction::Ignore => sigaction {
+            *c_oact = match old_action.kind {
+                SigactionKind::Ignore => sigaction {
                     sa_handler: unsafe { core::mem::transmute(SIG_IGN) },
                     sa_flags: 0,
                     sa_restorer: None,
                     sa_mask: 0,
                 },
-                Sigaction::Default => sigaction {
+                SigactionKind::Default => sigaction {
                     sa_handler: unsafe { core::mem::transmute(SIG_DFL) },
                     sa_flags: 0,
                     sa_restorer: None,
                     sa_mask: 0,
                 },
-                Sigaction::Handled { handler, mask, flags } => sigaction {
-                    sa_handler: if flags.contains(SigactionFlags::SIGINFO) {
+                SigactionKind::Handled { handler } => sigaction {
+                    sa_handler: if old_action.flags.contains(SigactionFlags::SIGINFO) {
                         unsafe { core::mem::transmute(handler.sigaction) }
                     } else {
                         unsafe { handler.handler }
                     },
                     sa_restorer: None,
-                    sa_flags: flags.bits().into(),
-                    sa_mask: mask,
+                    sa_flags: old_action.flags.bits().into(),
+                    sa_mask: old_action.mask,
                 },
             };
         }