From c43210f67be938e14f8193cc87309a5469ef3705 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 24 Oct 2022 02:34:48 +0100 Subject: [PATCH 1/2] Pass on null handle values to child process --- library/std/src/sys/windows/process.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 9cbb4ef19e9b7..32be07aee8f41 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -513,9 +513,6 @@ fn program_exists(path: &Path) -> Option> { impl Stdio { fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option) -> io::Result { match *self { - // If no stdio handle is available, then inherit means that it - // should still be unavailable so propagate the - // INVALID_HANDLE_VALUE. Stdio::Inherit => match stdio::get_handle(stdio_id) { Ok(io) => unsafe { let io = Handle::from_raw_handle(io); @@ -523,7 +520,8 @@ impl Stdio { io.into_raw_handle(); ret }, - Err(..) => unsafe { Ok(Handle::from_raw_handle(c::INVALID_HANDLE_VALUE)) }, + // If no stdio handle is available, then propagate the null value. + Err(..) => unsafe { Ok(Handle::from_raw_handle(ptr::null_mut())) }, }, Stdio::MakePipe => { @@ -730,9 +728,9 @@ fn zeroed_startupinfo() -> c::STARTUPINFO { wShowWindow: 0, cbReserved2: 0, lpReserved2: ptr::null_mut(), - hStdInput: c::INVALID_HANDLE_VALUE, - hStdOutput: c::INVALID_HANDLE_VALUE, - hStdError: c::INVALID_HANDLE_VALUE, + hStdInput: ptr::null_mut(), + hStdOutput: ptr::null_mut(), + hStdError: ptr::null_mut(), } } From 93b774a2a47e813fd01481dab480d4be785c4427 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 6 Dec 2022 16:54:32 +0000 Subject: [PATCH 2/2] Don't set `STARTF_USESTDHANDLES` if none are set --- library/std/src/sys/windows/process.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 32be07aee8f41..31e9b34fb9efd 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -252,10 +252,6 @@ impl Command { ) -> io::Result<(Process, StdioPipes)> { let maybe_env = self.env.capture_if_changed(); - let mut si = zeroed_startupinfo(); - si.cb = mem::size_of::() as c::DWORD; - si.dwFlags = c::STARTF_USESTDHANDLES; - let child_paths = if let Some(env) = maybe_env.as_ref() { env.get(&EnvKey::new("PATH")).map(|s| s.as_os_str()) } else { @@ -314,9 +310,21 @@ impl Command { let stdin = stdin.to_handle(c::STD_INPUT_HANDLE, &mut pipes.stdin)?; let stdout = stdout.to_handle(c::STD_OUTPUT_HANDLE, &mut pipes.stdout)?; let stderr = stderr.to_handle(c::STD_ERROR_HANDLE, &mut pipes.stderr)?; - si.hStdInput = stdin.as_raw_handle(); - si.hStdOutput = stdout.as_raw_handle(); - si.hStdError = stderr.as_raw_handle(); + + let mut si = zeroed_startupinfo(); + si.cb = mem::size_of::() as c::DWORD; + + // If at least one of stdin, stdout or stderr are set (i.e. are non null) + // then set the `hStd` fields in `STARTUPINFO`. + // Otherwise skip this and allow the OS to apply its default behaviour. + // This provides more consistent behaviour between Win7 and Win8+. + let is_set = |stdio: &Handle| !stdio.as_raw_handle().is_null(); + if is_set(&stderr) || is_set(&stdout) || is_set(&stdin) { + si.dwFlags |= c::STARTF_USESTDHANDLES; + si.hStdInput = stdin.as_raw_handle(); + si.hStdOutput = stdout.as_raw_handle(); + si.hStdError = stderr.as_raw_handle(); + } unsafe { cvt(c::CreateProcessW(