Skip to content

Commit fda3347

Browse files
committed
std: Fix inheriting standard handles on windows
Currently if a standard I/O handle is set to inherited on Windows, no action is taken and the slot in the process information description is set to `INVALID_HANDLE_VALUE`. Due to our passing of `STARTF_USESTDHANDLES`, however, this means that the handle is actually set to nothing and if a child tries to print it will generate an error. This commit fixes this behavior by explicitly creating stdio handles to be placed in these slots by duplicating the current process's I/O handles. This is presumably what previously happened silently by using a file-descriptor-based implementation instead of a `HANDLE`-centric implementation. Along the way this cleans up a lot of code in `Process::spawn` for Windows by ensuring destructors are always run, using more RAII, and limiting the scope of `unsafe` wherever possible.
1 parent 857ef6e commit fda3347

File tree

4 files changed

+133
-164
lines changed

4 files changed

+133
-164
lines changed

src/libstd/sys/windows/fs2.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ pub struct OpenOptions {
5656
share_mode: Option<libc::DWORD>,
5757
creation_disposition: Option<libc::DWORD>,
5858
flags_and_attributes: Option<libc::DWORD>,
59+
security_attributes: usize, // *mut T doesn't have a Default impl
5960
}
6061

6162
#[derive(Clone, PartialEq, Eq, Debug)]
@@ -135,6 +136,9 @@ impl OpenOptions {
135136
pub fn share_mode(&mut self, val: i32) {
136137
self.share_mode = Some(val as libc::DWORD);
137138
}
139+
pub fn security_attributes(&mut self, attrs: libc::LPSECURITY_ATTRIBUTES) {
140+
self.security_attributes = attrs as usize;
141+
}
138142

139143
fn get_desired_access(&self) -> libc::DWORD {
140144
self.desired_access.unwrap_or({
@@ -186,7 +190,7 @@ impl File {
186190
libc::CreateFileW(path.as_ptr(),
187191
opts.get_desired_access(),
188192
opts.get_share_mode(),
189-
ptr::null_mut(),
193+
opts.security_attributes as *mut _,
190194
opts.get_creation_disposition(),
191195
opts.get_flags_and_attributes(),
192196
ptr::null_mut())
@@ -263,6 +267,8 @@ impl File {
263267
}
264268

265269
pub fn handle(&self) -> &Handle { &self.handle }
270+
271+
pub fn into_handle(self) -> Handle { self.handle }
266272
}
267273

268274
impl FromInner<libc::HANDLE> for File {

src/libstd/sys/windows/handle.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use prelude::v1::*;
1212

1313
use io::ErrorKind;
1414
use io;
15+
use libc::funcs::extra::kernel32::{GetCurrentProcess, DuplicateHandle};
1516
use libc::{self, HANDLE};
1617
use mem;
1718
use ptr;
@@ -65,6 +66,18 @@ impl Handle {
6566
}));
6667
Ok(amt as usize)
6768
}
69+
70+
pub fn duplicate(&self, access: libc::DWORD, inherit: bool,
71+
options: libc::DWORD) -> io::Result<Handle> {
72+
let mut ret = 0 as libc::HANDLE;
73+
try!(cvt(unsafe {
74+
let cur_proc = GetCurrentProcess();
75+
DuplicateHandle(cur_proc, self.0, cur_proc, &mut ret,
76+
access, inherit as libc::BOOL,
77+
options)
78+
}));
79+
Ok(Handle::new(ret))
80+
}
6881
}
6982

7083
impl Drop for Handle {

0 commit comments

Comments
 (0)