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.
This commit is contained in:
Alex Crichton
2015-04-03 15:44:14 -07:00
parent 33a2191d0b
commit eadc3bcd67
5 changed files with 86 additions and 67 deletions

View File

@@ -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);