Skip to content

Commit a691f1e

Browse files
committed
Auto merge of #24426 - alexcrichton:windows-pipes, r=aturon
This commit removes the last remnants of file descriptors from the Windows implementation of `std::sys` by using `CreatePipe` to create anonymous pipes instead of the `pipe` shim provided in msvcrt.
2 parents af1c39c + 5e07329 commit a691f1e

File tree

4 files changed

+46
-82
lines changed

4 files changed

+46
-82
lines changed

src/libstd/sys/windows/c.rs

+4
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,10 @@ extern "system" {
465465
nOutBufferSize: libc::DWORD,
466466
lpBytesReturned: libc::LPDWORD,
467467
lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL;
468+
pub fn CreatePipe(hReadPipe: libc::LPHANDLE,
469+
hWritePipe: libc::LPHANDLE,
470+
lpPipeAttributes: libc::LPSECURITY_ATTRIBUTES,
471+
nSize: libc::DWORD) -> libc::BOOL;
468472
}
469473

470474
#[link(name = "userenv")]

src/libstd/sys/windows/handle.rs

+25-34
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,34 @@ impl Handle {
3636
}
3737

3838
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
39-
read(self.0, buf)
39+
let mut read = 0;
40+
let res = cvt(unsafe {
41+
libc::ReadFile(self.0, buf.as_ptr() as libc::LPVOID,
42+
buf.len() as libc::DWORD, &mut read,
43+
ptr::null_mut())
44+
});
45+
46+
match res {
47+
Ok(_) => Ok(read as usize),
48+
49+
// The special treatment of BrokenPipe is to deal with Windows
50+
// pipe semantics, which yields this error when *reading* from
51+
// a pipe after the other end has closed; we interpret that as
52+
// EOF on the pipe.
53+
Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(0),
54+
55+
Err(e) => Err(e)
56+
}
4057
}
4158

4259
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
43-
write(self.0, buf)
60+
let mut amt = 0;
61+
try!(cvt(unsafe {
62+
libc::WriteFile(self.0, buf.as_ptr() as libc::LPVOID,
63+
buf.len() as libc::DWORD, &mut amt,
64+
ptr::null_mut())
65+
}));
66+
Ok(amt as usize)
4467
}
4568
}
4669

@@ -49,35 +72,3 @@ impl Drop for Handle {
4972
unsafe { let _ = libc::CloseHandle(self.0); }
5073
}
5174
}
52-
53-
54-
pub fn read(h: HANDLE, buf: &mut [u8]) -> io::Result<usize> {
55-
let mut read = 0;
56-
let res = cvt(unsafe {
57-
libc::ReadFile(h, buf.as_ptr() as libc::LPVOID,
58-
buf.len() as libc::DWORD, &mut read,
59-
ptr::null_mut())
60-
});
61-
62-
match res {
63-
Ok(_) => Ok(read as usize),
64-
65-
// The special treatment of BrokenPipe is to deal with Windows
66-
// pipe semantics, which yields this error when *reading* from
67-
// a pipe after the other end has closed; we interpret that as
68-
// EOF on the pipe.
69-
Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(0),
70-
71-
Err(e) => Err(e)
72-
}
73-
}
74-
75-
pub fn write(h: HANDLE, buf: &[u8]) -> io::Result<usize> {
76-
let mut amt = 0;
77-
try!(cvt(unsafe {
78-
libc::WriteFile(h, buf.as_ptr() as libc::LPVOID,
79-
buf.len() as libc::DWORD, &mut amt,
80-
ptr::null_mut())
81-
}));
82-
Ok(amt as usize)
83-
}

src/libstd/sys/windows/pipe2.rs

+16-47
Original file line numberDiff line numberDiff line change
@@ -10,70 +10,39 @@
1010

1111
use prelude::v1::*;
1212

13-
use sys::handle;
1413
use io;
15-
use libc::{self, c_int, HANDLE};
14+
use libc;
15+
use sys::cvt;
16+
use sys::c;
17+
use sys::handle::Handle;
1618

1719
////////////////////////////////////////////////////////////////////////////////
1820
// Anonymous pipes
1921
////////////////////////////////////////////////////////////////////////////////
2022

2123
pub struct AnonPipe {
22-
fd: c_int
24+
inner: Handle,
2325
}
2426

2527
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
26-
// Windows pipes work subtly differently than unix pipes, and their
27-
// inheritance has to be handled in a different way that I do not
28-
// fully understand. Here we explicitly make the pipe non-inheritable,
29-
// which means to pass it to a subprocess they need to be duplicated
30-
// first, as in std::run.
31-
let mut fds = [0; 2];
32-
unsafe {
33-
match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint,
34-
(libc::O_BINARY | libc::O_NOINHERIT) as c_int) {
35-
0 => {
36-
assert!(fds[0] != -1 && fds[0] != 0);
37-
assert!(fds[1] != -1 && fds[1] != 0);
38-
39-
Ok((AnonPipe::from_fd(fds[0]), AnonPipe::from_fd(fds[1])))
40-
}
41-
_ => Err(io::Error::last_os_error()),
42-
}
43-
}
28+
let mut reader = libc::INVALID_HANDLE_VALUE;
29+
let mut writer = libc::INVALID_HANDLE_VALUE;
30+
try!(cvt(unsafe {
31+
c::CreatePipe(&mut reader, &mut writer, 0 as *mut _, 0)
32+
}));
33+
let reader = Handle::new(reader);
34+
let writer = Handle::new(writer);
35+
Ok((AnonPipe { inner: reader }, AnonPipe { inner: writer }))
4436
}
4537

4638
impl AnonPipe {
47-
pub fn from_fd(fd: libc::c_int) -> AnonPipe {
48-
AnonPipe { fd: fd }
49-
}
50-
51-
pub fn raw(&self) -> HANDLE {
52-
unsafe { libc::get_osfhandle(self.fd) as libc::HANDLE }
53-
}
39+
pub fn handle(&self) -> &Handle { &self.inner }
5440

5541
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
56-
handle::read(self.raw(), buf)
42+
self.inner.read(buf)
5743
}
5844

5945
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
60-
handle::write(self.raw(), buf)
61-
}
62-
}
63-
64-
impl Drop for AnonPipe {
65-
fn drop(&mut self) {
66-
// closing stdio file handles makes no sense, so never do it. Also, note
67-
// that errors are ignored when closing a file descriptor. The reason
68-
// for this is that if an error occurs we don't actually know if the
69-
// file descriptor was closed or not, and if we retried (for something
70-
// like EINTR), we might close another valid file descriptor (opened
71-
// after we closed ours.
72-
if self.fd > libc::STDERR_FILENO {
73-
let n = unsafe { libc::close(self.fd) };
74-
if n != 0 {
75-
println!("error {} when closing file descriptor {}", n, self.fd);
76-
}
77-
}
46+
self.inner.write(buf)
7847
}
7948
}

src/libstd/sys/windows/process2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ impl Process {
199199
}
200200
}
201201
Stdio::Piped(ref pipe) => {
202-
let orig = pipe.raw();
202+
let orig = pipe.handle().raw();
203203
if DuplicateHandle(cur_proc, orig, cur_proc, slot,
204204
0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
205205
return Err(Error::last_os_error())

0 commit comments

Comments
 (0)