about summary refs log tree commit diff
path: root/src/libnative/io/process.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnative/io/process.rs')
-rw-r--r--src/libnative/io/process.rs81
1 files changed, 55 insertions, 26 deletions
diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs
index 1218fab05f0..d1edea4df71 100644
--- a/src/libnative/io/process.rs
+++ b/src/libnative/io/process.rs
@@ -40,6 +40,9 @@ pub struct Process {
 
     /// None until finish() is called.
     exit_code: Option<p::ProcessExit>,
+
+    /// Manually delivered signal
+    exit_signal: Option<int>,
 }
 
 impl Process {
@@ -107,7 +110,12 @@ impl Process {
 
         match res {
             Ok(res) => {
-                Ok((Process { pid: res.pid, handle: res.handle, exit_code: None },
+                Ok((Process {
+                        pid: res.pid,
+                        handle: res.handle,
+                        exit_code: None,
+                        exit_signal: None,
+                    },
                     ret_io))
             }
             Err(e) => Err(e)
@@ -127,6 +135,14 @@ impl rtio::RtioProcess for Process {
             Some(code) => code,
             None => {
                 let code = waitpid(self.pid);
+                // On windows, waitpid will never return a signal. If a signal
+                // was successfully delivered to the process, however, we can
+                // consider it as having died via a signal.
+                let code = match self.exit_signal {
+                    None => code,
+                    Some(signal) if cfg!(windows) => p::ExitSignal(signal),
+                    Some(..) => code,
+                };
                 self.exit_code = Some(code);
                 code
             }
@@ -157,7 +173,14 @@ impl rtio::RtioProcess for Process {
             }),
             None => {}
         }
-        return unsafe { killpid(self.pid, signum) };
+
+        // A successfully delivered signal that isn't 0 (just a poll for being
+        // alive) is recorded for windows (see wait())
+        match unsafe { killpid(self.pid, signum) } {
+            Ok(()) if signum == 0 => Ok(()),
+            Ok(()) => { self.exit_signal = Some(signum); Ok(()) }
+            Err(e) => Err(e),
+        }
     }
 }
 
@@ -256,31 +279,37 @@ fn spawn_process_os(config: p::ProcessConfig,
 
         let cur_proc = GetCurrentProcess();
 
-        let orig_std_in = get_osfhandle(in_fd) as HANDLE;
-        if orig_std_in == INVALID_HANDLE_VALUE as HANDLE {
-            fail!("failure in get_osfhandle: {}", os::last_os_error());
-        }
-        if DuplicateHandle(cur_proc, orig_std_in, cur_proc, &mut si.hStdInput,
-                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!("failure in DuplicateHandle: {}", os::last_os_error());
+        if in_fd != -1 {
+            let orig_std_in = get_osfhandle(in_fd) as HANDLE;
+            if orig_std_in == INVALID_HANDLE_VALUE as HANDLE {
+                fail!("failure in get_osfhandle: {}", os::last_os_error());
+            }
+            if DuplicateHandle(cur_proc, orig_std_in, cur_proc, &mut si.hStdInput,
+                               0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+                fail!("failure in DuplicateHandle: {}", os::last_os_error());
+            }
         }
 
-        let orig_std_out = get_osfhandle(out_fd) as HANDLE;
-        if orig_std_out == INVALID_HANDLE_VALUE as HANDLE {
-            fail!("failure in get_osfhandle: {}", os::last_os_error());
-        }
-        if DuplicateHandle(cur_proc, orig_std_out, cur_proc, &mut si.hStdOutput,
-                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!("failure in DuplicateHandle: {}", os::last_os_error());
+        if out_fd != -1 {
+            let orig_std_out = get_osfhandle(out_fd) as HANDLE;
+            if orig_std_out == INVALID_HANDLE_VALUE as HANDLE {
+                fail!("failure in get_osfhandle: {}", os::last_os_error());
+            }
+            if DuplicateHandle(cur_proc, orig_std_out, cur_proc, &mut si.hStdOutput,
+                               0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+                fail!("failure in DuplicateHandle: {}", os::last_os_error());
+            }
         }
 
-        let orig_std_err = get_osfhandle(err_fd) as HANDLE;
-        if orig_std_err == INVALID_HANDLE_VALUE as HANDLE {
-            fail!("failure in get_osfhandle: {}", os::last_os_error());
-        }
-        if DuplicateHandle(cur_proc, orig_std_err, cur_proc, &mut si.hStdError,
-                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!("failure in DuplicateHandle: {}", os::last_os_error());
+        if err_fd != -1 {
+            let orig_std_err = get_osfhandle(err_fd) as HANDLE;
+            if orig_std_err == INVALID_HANDLE_VALUE as HANDLE {
+                fail!("failure in get_osfhandle: {}", os::last_os_error());
+            }
+            if DuplicateHandle(cur_proc, orig_std_err, cur_proc, &mut si.hStdError,
+                               0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+                fail!("failure in DuplicateHandle: {}", os::last_os_error());
+            }
         }
 
         let cmd = make_command_line(config.program, config.args);
@@ -307,9 +336,9 @@ fn spawn_process_os(config: p::ProcessConfig,
             })
         });
 
-        assert!(CloseHandle(si.hStdInput) != 0);
-        assert!(CloseHandle(si.hStdOutput) != 0);
-        assert!(CloseHandle(si.hStdError) != 0);
+        if in_fd != -1 { assert!(CloseHandle(si.hStdInput) != 0); }
+        if out_fd != -1 { assert!(CloseHandle(si.hStdOutput) != 0); }
+        if err_fd != -1 { assert!(CloseHandle(si.hStdError) != 0); }
 
         match create_err {
             Some(err) => return Err(err),