diff --git a/src/sys/redox.rs b/src/sys/redox.rs
index 2b87d0cdc2ebe8945b12b3e96cc75f4b5a9e792e..bcba1df0e58b4a53cc6f64c7bd43a6d6e9dc7f8b 100644
--- a/src/sys/redox.rs
+++ b/src/sys/redox.rs
@@ -104,8 +104,7 @@ pub mod job_control {
 
     use shell::Shell;
     use shell::foreground::ForegroundSignals;
-    use shell::status::TERMINATED;
-    use std::io::{self, Write};
+    use shell::status::{FAILURE, TERMINATED};
     use std::os::unix::process::ExitStatusExt;
     use std::process::ExitStatus;
     use std::sync::{Arc, Mutex};
@@ -122,35 +121,53 @@ pub mod job_control {
 
 
     pub fn watch_foreground<'a, F, D>(
-        _shell: &mut Shell<'a>,
-        pid: u32,
-        _last_pid: u32,
+        shell: &mut Shell<'a>,
+        _pid: u32,
+        last_pid: u32,
         _get_command: F,
-        mut _drop_command: D,
+        mut drop_command: D,
     ) -> i32
         where F: FnOnce() -> String,
               D: FnMut(i32)
     {
+        let mut exit_status = 0;
         loop {
             let mut status_raw = 0;
-            match syscall::waitpid(pid as usize, &mut status_raw, 0) {
-                Ok(0) => (),
-                Ok(_pid) => {
+            match syscall::waitpid(0, &mut status_raw, 0) {
+                Ok(pid) => {
                     let status = ExitStatus::from_raw(status_raw as i32);
                     if let Some(code) = status.code() {
-                        break code;
+                        if pid == (last_pid as usize) {
+                            break code;
+                        } else {
+                            drop_command(pid as i32);
+                            exit_status = code;
+                        }
+                    } else if let Some(signal) = status.signal() {
+                        eprintln!("ion: process ended by signal: {}", signal);
+                        if signal == syscall::SIGTERM as i32 {
+                            shell.handle_signal(signal);
+                            shell.exit(TERMINATED);
+                        } else if signal == syscall::SIGHUP as i32 {
+                            shell.handle_signal(signal);
+                            shell.exit(TERMINATED);
+                        } else if signal == syscall::SIGINT as i32 {
+                            shell.foreground_send(signal);
+                            shell.break_flow = true;
+                        }
+                        break TERMINATED;
                     } else {
-                        let stderr = io::stderr();
-                        let mut stderr = stderr.lock();
-                        let _ = stderr.write_all(b"ion: child ended by signal\n");
+                        eprintln!("ion: process ended with unknown status: {}", status);
                         break TERMINATED;
                     }
                 }
                 Err(err) => {
-                    let stderr = io::stderr();
-                    let mut stderr = stderr.lock();
-                    let _ = writeln!(stderr, "ion: failed to wait: {}", err);
-                    break 100; // TODO what should we return here?
+                    if err.errno == syscall::ECHILD {
+                        break exit_status;
+                    } else {
+                        eprintln!("ion: process doesn't exist: {}", err);
+                        break FAILURE;
+                    }
                 }
             }
         }