From 6afa32a2504fa90b48f74979bb4061cb397e9270 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 12 Feb 2016 10:28:03 -0800 Subject: std: Don't always create stdin for children For example if `Command::output` or `Command::status` is used then stdin is just immediately closed. Add an option for this so as an optimization we can avoid creating pipes entirely. This should help reduce the number of active file descriptors when spawning processes on Unix and the number of active handles on Windows. --- src/libstd/sys/unix/process.rs | 13 ++++++++----- src/libstd/sys/windows/process.rs | 6 ++++-- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 28475f50ce6..5696cb2b52f 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -216,7 +216,7 @@ impl Command { self.stderr = Some(stderr); } - pub fn spawn(&mut self, default: Stdio) + pub fn spawn(&mut self, default: Stdio, needs_stdin: bool) -> io::Result<(Process, StdioPipes)> { const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX"; @@ -225,7 +225,7 @@ impl Command { "nul byte found in provided data")); } - let (ours, theirs) = try!(self.setup_io(default)); + let (ours, theirs) = try!(self.setup_io(default, needs_stdin)); let (input, output) = try!(sys::pipe::anon_pipe()); let pid = unsafe { @@ -298,7 +298,7 @@ impl Command { "nul byte found in provided data") } - match self.setup_io(default) { + match self.setup_io(default, true) { Ok((_, theirs)) => unsafe { self.do_exec(theirs) }, Err(e) => e, } @@ -408,8 +408,11 @@ impl Command { } - fn setup_io(&self, default: Stdio) -> io::Result<(StdioPipes, ChildPipes)> { - let stdin = self.stdin.as_ref().unwrap_or(&default); + fn setup_io(&self, default: Stdio, needs_stdin: bool) + -> io::Result<(StdioPipes, ChildPipes)> { + let null = Stdio::Null; + let default_stdin = if needs_stdin {&default} else {&null}; + let stdin = self.stdin.as_ref().unwrap_or(default_stdin); let stdout = self.stdout.as_ref().unwrap_or(&default); let stderr = self.stderr.as_ref().unwrap_or(&default); let (their_stdin, our_stdin) = try!(stdin.to_child_stdio(true)); diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index fa118be6fe6..524c932eed4 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -123,7 +123,7 @@ impl Command { self.stderr = Some(stderr); } - pub fn spawn(&mut self, default: Stdio) + pub fn spawn(&mut self, default: Stdio, needs_stdin: bool) -> io::Result<(Process, StdioPipes)> { // To have the spawning semantics of unix/windows stay the same, we need // to read the *child's* PATH if one is provided. See #15149 for more @@ -181,7 +181,9 @@ impl Command { stdout: None, stderr: None, }; - let stdin = self.stdin.as_ref().unwrap_or(&default); + let null = Stdio::Null; + let default_stdin = if needs_stdin {&default} else {&null}; + let stdin = self.stdin.as_ref().unwrap_or(default_stdin); let stdout = self.stdout.as_ref().unwrap_or(&default); let stderr = self.stderr.as_ref().unwrap_or(&default); let stdin = try!(stdin.to_handle(c::STD_INPUT_HANDLE, &mut pipes.stdin)); -- cgit 1.4.1-3-g733a5