|
10 | 10 |
|
11 | 11 | use prelude::v1::*; |
12 | 12 |
|
13 | | -use sys::handle; |
14 | 13 | 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; |
16 | 18 |
|
17 | 19 | //////////////////////////////////////////////////////////////////////////////// |
18 | 20 | // Anonymous pipes |
19 | 21 | //////////////////////////////////////////////////////////////////////////////// |
20 | 22 |
|
21 | 23 | pub struct AnonPipe { |
22 | | - fd: c_int |
| 24 | + inner: Handle, |
23 | 25 | } |
24 | 26 |
|
25 | 27 | 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 })) |
44 | 36 | } |
45 | 37 |
|
46 | 38 | 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 } |
54 | 40 |
|
55 | 41 | pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { |
56 | | - handle::read(self.raw(), buf) |
| 42 | + self.inner.read(buf) |
57 | 43 | } |
58 | 44 |
|
59 | 45 | 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) |
78 | 47 | } |
79 | 48 | } |
0 commit comments