diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs
index 7d2e0e92634512119cbce64bc6460275df414421..984890cc1b9b083e4a27e41fc7ce89ebeaa6e775 100644
--- a/src/platform/redox/mod.rs
+++ b/src/platform/redox/mod.rs
@@ -925,22 +925,38 @@ impl Pal for Sys {
         let mut status = 0;
 
         // First, allow ptrace to handle waitpid
+        // TODO: Handle special PIDs here (such as -1)
         let state = ptrace::init_state();
-        let sessions = state.sessions.lock();
-        if let Some(session) = sessions.get(&pid) {
+        let mut sessions = state.sessions.lock();
+        if let Ok(session) = ptrace::get_session(&mut sessions, pid) {
             if options & sys_wait::WNOHANG != sys_wait::WNOHANG {
                 let _ = (&mut &session.tracer).write(&[syscall::PTRACE_WAIT]);
-                res = Some(e(syscall::waitpid(pid as usize, &mut status, (options | sys_wait::WNOHANG) as usize)));
+                res = Some(e(syscall::waitpid(
+                    pid as usize, &mut status,
+                    (options | sys_wait::WNOHANG | sys_wait::WUNTRACED) as usize
+                )));
                 if res == Some(0) {
                     // WNOHANG, just pretend ptrace SIGSTOP:ped this
                     status = (syscall::SIGSTOP << 8) | 0x7f;
+                    assert!(syscall::wifstopped(status));
+                    assert_eq!(syscall::wstopsig(status), syscall::SIGSTOP);
                     res = Some(pid as usize);
                 }
             }
         }
 
-        // If ptrace didn't impact this waitpid, proceed as normal
-        let res = res.unwrap_or_else(|| e(syscall::waitpid(pid as usize, &mut status, options as usize)));
+        // If ptrace didn't impact this waitpid, proceed *almost* as
+        // normal: We still need to add WUNTRACED, but we only return
+        // it if (and only if) a ptrace traceme was activated during
+        // the wait.
+        let res = res.unwrap_or_else(|| loop {
+            let res = e(syscall::waitpid(pid as usize, &mut status, (options | sys_wait::WUNTRACED) as usize));
+
+            // TODO: Also handle special PIDs here
+            if !syscall::wifstopped(res) || ptrace::is_traceme(pid) {
+                break res;
+            }
+        });
 
         // If stat_loc is non-null, set that and the return
         unsafe {
diff --git a/src/platform/redox/ptrace.rs b/src/platform/redox/ptrace.rs
index da82cd76f332aa4f99ff667bc5a4a6b053c27969..e80a00bce879aa3bdd4a7b35539327bcd332ff1e 100644
--- a/src/platform/redox/ptrace.rs
+++ b/src/platform/redox/ptrace.rs
@@ -14,6 +14,7 @@ use crate::io::{self, prelude::*};
 use crate::sync::{Mutex, Once};
 use alloc::collections::BTreeMap;
 use alloc::collections::btree_map::Entry;
+use core::mem;
 use syscall;
 
 pub struct Session {
@@ -38,34 +39,51 @@ static STATE: Once<State> = Once::new();
 pub fn init_state() -> &'static State {
     STATE.call_once(|| State::new())
 }
+pub fn is_traceme(pid: pid_t) -> bool {
+    File::open(&CString::new(format!("chan:ptrace-relibc/{}/traceme", pid)).unwrap(), fcntl::O_PATH).is_ok()
+}
+pub fn get_session(sessions: &mut BTreeMap<pid_t, Session>, pid: pid_t) -> io::Result<&Session> {
+    const NEW_FLAGS: c_int = fcntl::O_RDWR | fcntl::O_CLOEXEC;
+
+    match sessions.entry(pid) {
+        Entry::Vacant(entry) => if is_traceme(pid) {
+            Ok(entry.insert(Session {
+                tracer: File::open(&CString::new(format!("proc:{}/trace", pid)).unwrap(), NEW_FLAGS | fcntl::O_NONBLOCK)?,
+                mem: File::open(&CString::new(format!("proc:{}/mem", pid)).unwrap(), NEW_FLAGS)?,
+                regs: File::open(&CString::new(format!("proc:{}/regs/int", pid)).unwrap(), NEW_FLAGS)?,
+                fpregs: File::open(&CString::new(format!("proc:{}/regs/float", pid)).unwrap(), NEW_FLAGS)?,
+            }))
+        } else {
+            unsafe { errno = errnoh::ESRCH; }
+            Err(io::last_os_error())
+        },
+        Entry::Occupied(entry) => Ok(entry.into_mut())
+    }
+}
 
 fn inner_ptrace(request: c_int, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> io::Result<c_int> {
     let state = init_state();
 
     if request == sys_ptrace::PTRACE_TRACEME {
-        // let pid = Sys::getpid();
-        // todo: only auto-open session on host if this happens
+        // Mark this child as traced, parent will check for this marker file
+        let pid = Sys::getpid();
+        mem::forget(File::open(
+            &CString::new(format!("chan:ptrace-relibc/{}/traceme", pid)).unwrap(),
+            fcntl::O_CREAT | fcntl::O_PATH | fcntl::O_EXCL
+        )?);
         return Ok(0);
     }
 
-    const NEW_FLAGS: c_int = fcntl::O_RDWR | fcntl::O_CLOEXEC;
-
     let mut sessions = state.sessions.lock();
-    let session = match sessions.entry(pid) {
-        Entry::Vacant(entry) => entry.insert(Session {
-            tracer: File::open(&CString::new(format!("proc:{}/trace", pid)).unwrap(), NEW_FLAGS | fcntl::O_NONBLOCK)?,
-            mem: File::open(&CString::new(format!("proc:{}/mem", pid)).unwrap(), NEW_FLAGS)?,
-            regs: File::open(&CString::new(format!("proc:{}/regs/int", pid)).unwrap(), NEW_FLAGS)?,
-            fpregs: File::open(&CString::new(format!("proc:{}/regs/float", pid)).unwrap(), NEW_FLAGS)?,
-        }),
-        Entry::Occupied(entry) => entry.into_mut()
-    };
+    let session = get_session(&mut sessions, pid)?;
+
     match request {
         sys_ptrace::PTRACE_CONT | sys_ptrace::PTRACE_SINGLESTEP |
         sys_ptrace::PTRACE_SYSCALL | sys_ptrace::PTRACE_SYSEMU |
         sys_ptrace::PTRACE_SYSEMU_SINGLESTEP => {
             Sys::kill(pid, signal::SIGCONT as _);
 
+            // TODO: Translate errors
             (&mut &session.tracer).write(&[match request {
                 sys_ptrace::PTRACE_CONT => syscall::PTRACE_CONT,
                 sys_ptrace::PTRACE_SINGLESTEP => syscall::PTRACE_SINGLESTEP,
diff --git a/tests/ptrace.c b/tests/ptrace.c
index c2a1760b30eba9b3c50b4242c563377b4f4c0f2d..4a5c5d4d78e328276f26064992181c405875c2c7 100644
--- a/tests/ptrace.c
+++ b/tests/ptrace.c
@@ -8,11 +8,26 @@
 
 #include "test_helpers.h"
 
+#ifdef __linux__
+
+const int SYS_write = 1;
+
+#endif
+#ifdef __redox__
+
+const int SYS_write = 0x21000004;
+
+#endif
+
 int main() {
     int pid = fork();
     ERROR_IF(fork, pid, == -1);
 
     if (pid == 0) {
+        // Test behavior on Redox when TRACEME hasn't been activated
+        // before waitpid is invoked!
+        sleep(1);
+
         int result = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
         ERROR_IF(ptrace, result, == -1);
         UNEXP_IF(ptrace, result, != 0);
@@ -28,7 +43,7 @@ int main() {
         puts("Big surprise, right!");
     } else {
         // Wait for child process to be ready
-        int result = waitpid(pid, NULL, WUNTRACED);
+        int result = waitpid(pid, NULL, 0);
         ERROR_IF(waitpid, result, == -1);
 
         int status;
@@ -45,7 +60,7 @@ int main() {
             result = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
             ERROR_IF(ptrace, result, == -1);
 
-            if (regs.orig_rax == 1 || regs.orig_rax == 0x21000004) { // SYS_write on Redox and Linux
+            if (regs.orig_rax == SYS_write || regs.orig_rax == SYS_write) {
                 regs.rdi = 2;
                 result = ptrace(PTRACE_SETREGS, pid, NULL, &regs);
                 ERROR_IF(ptrace, result, == -1);