diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-04-03 15:44:14 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-04-10 01:03:38 -0700 |
| commit | eadc3bcd676277d72c211bde6c20f7036339fd84 (patch) | |
| tree | 7ec781b484adac13c8b4ad3bbb676bb5383faa0e /src/libstd/sys/windows/process2.rs | |
| parent | 33a2191d0b880242b3bf9a32477a6b432f931c80 (diff) | |
| download | rust-eadc3bcd676277d72c211bde6c20f7036339fd84.tar.gz rust-eadc3bcd676277d72c211bde6c20f7036339fd84.zip | |
std: Unconditionally close all file descriptors
The logic for only closing file descriptors >= 3 was inherited from quite some time ago and ends up meaning that some internal APIs are less consistent than they should be. By unconditionally closing everything entering a `FileDesc` we ensure that we're consistent in our behavior as well as robustly handling the stdio case.
Diffstat (limited to 'src/libstd/sys/windows/process2.rs')
| -rw-r--r-- | src/libstd/sys/windows/process2.rs | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/src/libstd/sys/windows/process2.rs b/src/libstd/sys/windows/process2.rs index 7e832b6384d..74953921921 100644 --- a/src/libstd/sys/windows/process2.rs +++ b/src/libstd/sys/windows/process2.rs @@ -105,11 +105,18 @@ pub struct Process { handle: Handle, } +pub enum Stdio { + Inherit, + Piped(AnonPipe), + None, +} + impl Process { #[allow(deprecated)] pub fn spawn(cfg: &Command, - in_fd: Option<AnonPipe>, out_fd: Option<AnonPipe>, err_fd: Option<AnonPipe>) - -> io::Result<Process> + in_fd: Stdio, + out_fd: Stdio, + err_fd: Stdio) -> io::Result<Process> { use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO}; use libc::consts::os::extra::{ @@ -156,13 +163,16 @@ impl Process { let cur_proc = GetCurrentProcess(); - // Similarly to unix, we don't actually leave holes for the stdio file - // descriptors, but rather open up /dev/null equivalents. These - // equivalents are drawn from libuv's windows process spawning. - let set_fd = |fd: &Option<AnonPipe>, slot: &mut HANDLE, + let set_fd = |fd: &Stdio, slot: &mut HANDLE, is_stdin: bool| { match *fd { - None => { + Stdio::Inherit => {} + + // Similarly to unix, we don't actually leave holes for the + // stdio file descriptors, but rather open up /dev/null + // equivalents. These equivalents are drawn from libuv's + // windows process spawning. + Stdio::None => { let access = if is_stdin { libc::FILE_GENERIC_READ } else { @@ -188,11 +198,8 @@ impl Process { return Err(Error::last_os_error()) } } - Some(ref pipe) => { + Stdio::Piped(ref pipe) => { let orig = pipe.raw(); - if orig == INVALID_HANDLE_VALUE { - return Err(Error::last_os_error()) - } if DuplicateHandle(cur_proc, orig, cur_proc, slot, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE { return Err(Error::last_os_error()) @@ -235,9 +242,15 @@ impl Process { }) }); - assert!(CloseHandle(si.hStdInput) != 0); - assert!(CloseHandle(si.hStdOutput) != 0); - assert!(CloseHandle(si.hStdError) != 0); + if !in_fd.inherited() { + assert!(CloseHandle(si.hStdInput) != 0); + } + if !out_fd.inherited() { + assert!(CloseHandle(si.hStdOutput) != 0); + } + if !err_fd.inherited() { + assert!(CloseHandle(si.hStdError) != 0); + } match create_err { Some(err) => return Err(err), @@ -296,6 +309,12 @@ impl Process { } } +impl Stdio { + fn inherited(&self) -> bool { + match *self { Stdio::Inherit => true, _ => false } + } +} + #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct ExitStatus(i32); |
