diff options
| author | QuietMisdreavus <grey@quietmisdreavus.net> | 2017-04-09 10:38:38 -0500 |
|---|---|---|
| committer | QuietMisdreavus <grey@quietmisdreavus.net> | 2017-04-09 10:38:38 -0500 |
| commit | 8dd4c44ef6c851afcc9651c9b32df005e35d0d1d (patch) | |
| tree | 5dc8ec96361b673f8d4162821a97f8f021d83436 /src/libstd/sys | |
| parent | bfd01b7f40ae2cbfe9acbc1d10e79ffe16870df8 (diff) | |
| parent | 2c48ae6f7ffae392d85c86240c67f49df01f44fd (diff) | |
| download | rust-8dd4c44ef6c851afcc9651c9b32df005e35d0d1d.tar.gz rust-8dd4c44ef6c851afcc9651c9b32df005e35d0d1d.zip | |
merge with master to pick up pulldown switch
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/redox/fast_thread_local.rs | 6 | ||||
| -rw-r--r-- | src/libstd/sys/redox/process.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/unix/backtrace/mod.rs | 8 | ||||
| -rw-r--r-- | src/libstd/sys/unix/ext/net.rs | 40 | ||||
| -rw-r--r-- | src/libstd/sys/unix/fast_thread_local.rs | 8 | ||||
| -rw-r--r-- | src/libstd/sys/unix/fd.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/unix/fs.rs | 4 | ||||
| -rw-r--r-- | src/libstd/sys/unix/mod.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/unix/pipe.rs | 22 | ||||
| -rw-r--r-- | src/libstd/sys/unix/process/process_common.rs | 20 | ||||
| -rw-r--r-- | src/libstd/sys/unix/process/process_unix.rs | 13 | ||||
| -rw-r--r-- | src/libstd/sys/unix/stack_overflow.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/windows/ext/fs.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/windows/ext/process.rs | 1 | ||||
| -rw-r--r-- | src/libstd/sys/windows/process.rs | 9 | ||||
| -rw-r--r-- | src/libstd/sys/windows/stdio.rs | 92 |
16 files changed, 122 insertions, 111 deletions
diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs index 6eeae2d90ea..f6414673dac 100644 --- a/src/libstd/sys/redox/fast_thread_local.rs +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -96,17 +96,17 @@ pub unsafe extern fn destroy_value<T>(ptr: *mut u8) { // `None`. (*ptr).dtor_running.set(true); - // The OSX implementation of TLS apparently had an odd aspect to it + // The macOS implementation of TLS apparently had an odd aspect to it // where the pointer we have may be overwritten while this destructor // is running. Specifically if a TLS destructor re-accesses TLS it may // trigger a re-initialization of all TLS variables, paving over at // least some destroyed ones with initial values. // - // This means that if we drop a TLS value in place on OSX that we could + // This means that if we drop a TLS value in place on macOS that we could // revert the value to its original state halfway through the // destructor, which would be bad! // - // Hence, we use `ptr::read` on OSX (to move to a "safe" location) + // Hence, we use `ptr::read` on macOS (to move to a "safe" location) // instead of drop_in_place. if cfg!(target_os = "macos") { ptr::read((*ptr).inner.get()); diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 60dc03fcf47..707b4cbc6ac 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -249,7 +249,7 @@ impl Command { // mutex, and then after the fork they unlock it. // // Despite this information, libnative's spawn has been witnessed to - // deadlock on both OSX and FreeBSD. I'm not entirely sure why, but + // deadlock on both macOS and FreeBSD. I'm not entirely sure why, but // all collected backtraces point at malloc/free traffic in the // child spawned process. // diff --git a/src/libstd/sys/unix/backtrace/mod.rs b/src/libstd/sys/unix/backtrace/mod.rs index 29d4012dcdf..bf52da2ed4a 100644 --- a/src/libstd/sys/unix/backtrace/mod.rs +++ b/src/libstd/sys/unix/backtrace/mod.rs @@ -13,7 +13,7 @@ /// Some methods of getting a backtrace: /// /// * The backtrace() functions on unix. It turns out this doesn't work very -/// well for green threads on OSX, and the address to symbol portion of it +/// well for green threads on macOS, and the address to symbol portion of it /// suffers problems that are described below. /// /// * Using libunwind. This is more difficult than it sounds because libunwind @@ -51,9 +51,9 @@ /// /// * Use dladdr(). The original backtrace()-based idea actually uses dladdr() /// behind the scenes to translate, and this is why backtrace() was not used. -/// Conveniently, this method works fantastically on OSX. It appears dladdr() +/// Conveniently, this method works fantastically on macOS. It appears dladdr() /// uses magic to consult the local symbol table, or we're putting everything -/// in the dynamic symbol table anyway. Regardless, for OSX, this is the +/// in the dynamic symbol table anyway. Regardless, for macOS, this is the /// method used for translation. It's provided by the system and easy to do.o /// /// Sadly, all other systems have a dladdr() implementation that does not @@ -75,7 +75,7 @@ /// * Use `libbacktrace`. It turns out that this is a small library bundled in /// the gcc repository which provides backtrace and symbol translation /// functionality. All we really need from it is the backtrace functionality, -/// and we only really need this on everything that's not OSX, so this is the +/// and we only really need this on everything that's not macOS, so this is the /// chosen route for now. /// /// In summary, the current situation uses libgcc_s to get a trace of stack diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 1ba4a104e51..d688f2fa504 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -204,7 +204,7 @@ impl SocketAddr { let len = self.len as usize - sun_path_offset(); let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; - // OSX seems to return a len of 16 and a zeroed sun_path for unnamed addresses + // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses if len == 0 || (cfg!(not(target_os = "linux")) && self.addr.sun_path[0] == 0) { AddressKind::Unnamed } else if self.addr.sun_path[0] == 0 { @@ -375,12 +375,12 @@ impl UnixStream { /// Sets the read timeout for the socket. /// - /// If the provided value is [`None`], then [`read()`] calls will block + /// If the provided value is [`None`], then [`read`] calls will block /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../../../std/io/trait.Read.html#tymethod.read + /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples @@ -399,12 +399,12 @@ impl UnixStream { /// Sets the write timeout for the socket. /// - /// If the provided value is [`None`], then [`write()`] calls will block + /// If the provided value is [`None`], then [`write`] calls will block /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../../../std/io/trait.Write.html#tymethod.write + /// [`read`]: ../../../../std/io/trait.Write.html#tymethod.write /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples @@ -641,7 +641,7 @@ impl UnixListener { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; let (addr, len) = sockaddr_un(path)?; - cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len))?; + cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?; cvt(libc::listen(*inner.as_inner(), 128))?; Ok(UnixListener(inner)) @@ -920,7 +920,7 @@ impl UnixDatagram { let socket = UnixDatagram::unbound()?; let (addr, len) = sockaddr_un(path)?; - cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len))?; + cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?; Ok(socket) } @@ -974,12 +974,12 @@ impl UnixDatagram { /// Connects the socket to the specified address. /// - /// The [`send()`] method may be used to send data to the specified address. - /// [`recv()`] and [`recv_from()`] will only receive data from that address. + /// The [`send`] method may be used to send data to the specified address. + /// [`recv`] and [`recv_from`] will only receive data from that address. /// - /// [`send()`]: #method.send - /// [`recv()`]: #method.recv - /// [`recv_from()`]: #method.recv_from + /// [`send`]: #method.send + /// [`recv`]: #method.recv + /// [`recv_from`]: #method.recv_from /// /// # Examples /// @@ -1047,9 +1047,9 @@ impl UnixDatagram { /// Returns the address of this socket's peer. /// - /// The [`connect()`] method will connect the socket to a peer. + /// The [`connect`] method will connect the socket to a peer. /// - /// [`connect()`]: #method.connect + /// [`connect`]: #method.connect /// /// # Examples /// @@ -1178,13 +1178,13 @@ impl UnixDatagram { /// Sets the read timeout for the socket. /// - /// If the provided value is [`None`], then [`recv()`] and [`recv_from()`] calls will + /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will /// block indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`recv()`]: #method.recv - /// [`recv_from()`]: #method.recv_from + /// [`recv`]: #method.recv + /// [`recv_from`]: #method.recv_from /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples @@ -1203,13 +1203,13 @@ impl UnixDatagram { /// Sets the write timeout for the socket. /// - /// If the provided value is [`None`], then [`send()`] and [`send_to()`] calls will + /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will /// block indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`send()`]: #method.send - /// [`send_to()`]: #method.send_to + /// [`send`]: #method.send + /// [`send_to`]: #method.send_to /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index f4f73646e1b..07d76a93dd1 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -128,7 +128,7 @@ unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { register_dtor_fallback(t, dtor); } -// OSX's analog of the above linux function is this _tlv_atexit function. +// macOS's analog of the above linux function is this _tlv_atexit function. // The disassembly of thread_local globals in C++ (at least produced by // clang) will have this show up in the output. #[cfg(target_os = "macos")] @@ -154,17 +154,17 @@ pub unsafe extern fn destroy_value<T>(ptr: *mut u8) { // `None`. (*ptr).dtor_running.set(true); - // The OSX implementation of TLS apparently had an odd aspect to it + // The macOS implementation of TLS apparently had an odd aspect to it // where the pointer we have may be overwritten while this destructor // is running. Specifically if a TLS destructor re-accesses TLS it may // trigger a re-initialization of all TLS variables, paving over at // least some destroyed ones with initial values. // - // This means that if we drop a TLS value in place on OSX that we could + // This means that if we drop a TLS value in place on macOS that we could // revert the value to its original state halfway through the // destructor, which would be bad! // - // Hence, we use `ptr::read` on OSX (to move to a "safe" location) + // Hence, we use `ptr::read` on macOS (to move to a "safe" location) // instead of drop_in_place. if cfg!(target_os = "macos") { ptr::read((*ptr).inner.get()); diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index c690fd467ee..405fac2b9d7 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -29,7 +29,7 @@ fn max_len() -> usize { // with the man page quoting that if the count of bytes to read is // greater than `SSIZE_MAX` the result is "unspecified". // - // On OSX, however, apparently the 64-bit libc is either buggy or + // On macOS, however, apparently the 64-bit libc is either buggy or // intentionally showing odd behavior by rejecting any read with a size // larger than or equal to INT_MAX. To handle both of these the read // size is capped on both platforms. diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index d0fb96b1ff1..e893a139094 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -439,7 +439,7 @@ impl File { // Linux kernel then the flag is just ignored by the OS, so we continue // to explicitly ask for a CLOEXEC fd here. // - // The CLOEXEC flag, however, is supported on versions of OSX/BSD/etc + // The CLOEXEC flag, however, is supported on versions of macOS/BSD/etc // that we support, so we only do this on Linux currently. if cfg!(target_os = "linux") { fd.set_cloexec()?; @@ -573,7 +573,7 @@ impl fmt::Debug for File { #[cfg(target_os = "macos")] fn get_path(fd: c_int) -> Option<PathBuf> { // FIXME: The use of PATH_MAX is generally not encouraged, but it - // is inevitable in this case because OS X defines `fcntl` with + // is inevitable in this case because macOS defines `fcntl` with // `F_GETPATH` in terms of `MAXPATHLEN`, and there are no // alternatives. If a better method is invented, it should be used // instead. diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index c57751a01d7..854d380d128 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -92,7 +92,7 @@ pub fn init() { #[cfg(not(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia")))] unsafe fn reset_sigpipe() { - assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0); + assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); } #[cfg(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia"))] unsafe fn reset_sigpipe() {} diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 51e00fc1ab9..706256ff10e 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use cmp; use io; use libc::{self, c_int}; use mem; -use ptr; use sys::{cvt, cvt_r}; use sys::fd::FileDesc; @@ -80,16 +78,14 @@ pub fn read2(p1: AnonPipe, p1.set_nonblocking(true)?; p2.set_nonblocking(true)?; - let max = cmp::max(p1.raw(), p2.raw()); + let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() }; + fds[0].fd = p1.raw(); + fds[0].events = libc::POLLIN; + fds[1].fd = p2.raw(); + fds[1].events = libc::POLLIN; loop { - // wait for either pipe to become readable using `select` - cvt_r(|| unsafe { - let mut read: libc::fd_set = mem::zeroed(); - libc::FD_SET(p1.raw(), &mut read); - libc::FD_SET(p2.raw(), &mut read); - libc::select(max + 1, &mut read, ptr::null_mut(), ptr::null_mut(), - ptr::null_mut()) - })?; + // wait for either pipe to become readable using `poll` + cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?; // Read as much as we can from each pipe, ignoring EWOULDBLOCK or // EAGAIN. If we hit EOF, then this will happen because the underlying @@ -109,11 +105,11 @@ pub fn read2(p1: AnonPipe, } } }; - if read(&p1, v1)? { + if fds[0].revents != 0 && read(&p1, v1)? { p2.set_nonblocking(false)?; return p2.read_to_end(v2).map(|_| ()); } - if read(&p2, v2)? { + if fds[1].revents != 0 && read(&p2, v2)? { p1.set_nonblocking(false)?; return p1.read_to_end(v1).map(|_| ()); } diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index a4536520376..e9f41009064 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -417,13 +417,27 @@ mod tests { } } + // Android with api less than 21 define sig* functions inline, so it is not + // available for dynamic link. Implementing sigemptyset and sigaddset allow us + // to support older Android version (independent of libc version). + // The following implementations are based on https://git.io/vSkNf + #[cfg(not(target_os = "android"))] extern { + #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")] + fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")] fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int; } #[cfg(target_os = "android")] + unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int { + libc::memset(set as *mut _, 0, mem::size_of::<libc::sigset_t>()); + return 0; + } + + #[cfg(target_os = "android")] unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int { use slice; @@ -434,8 +448,8 @@ mod tests { } // See #14232 for more information, but it appears that signal delivery to a - // newly spawned process may just be raced in the OSX, so to prevent this - // test from being flaky we ignore it on OSX. + // newly spawned process may just be raced in the macOS, so to prevent this + // test from being flaky we ignore it on macOS. #[test] #[cfg_attr(target_os = "macos", ignore)] #[cfg_attr(target_os = "nacl", ignore)] // no signals on NaCl. @@ -450,7 +464,7 @@ mod tests { let mut set: libc::sigset_t = mem::uninitialized(); let mut old_set: libc::sigset_t = mem::uninitialized(); - t!(cvt(libc::sigemptyset(&mut set))); + t!(cvt(sigemptyset(&mut set))); t!(cvt(sigaddset(&mut set, libc::SIGINT))); t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut old_set))); diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index bbc987209e3..edd322ca6fa 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -129,7 +129,7 @@ impl Command { // mutex, and then after the fork they unlock it. // // Despite this information, libnative's spawn has been witnessed to - // deadlock on both OSX and FreeBSD. I'm not entirely sure why, but + // deadlock on both macOS and FreeBSD. I'm not entirely sure why, but // all collected backtraces point at malloc/free traffic in the // child spawned process. // @@ -193,7 +193,16 @@ impl Command { // need to clean things up now to avoid confusing the program // we're about to run. let mut set: libc::sigset_t = mem::uninitialized(); - t!(cvt(libc::sigemptyset(&mut set))); + if cfg!(target_os = "android") { + // Implementing sigemptyset allow us to support older Android + // versions. See the comment about Android and sig* functions in + // process_common.rs + libc::memset(&mut set as *mut _ as *mut _, + 0, + mem::size_of::<libc::sigset_t>()); + } else { + t!(cvt(libc::sigemptyset(&mut set))); + } t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, ptr::null_mut()))); let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL); diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 22d47ba0f62..51adbc24ae0 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -187,7 +187,7 @@ mod imp { let stack = libc::stack_t { ss_sp: ptr::null_mut(), ss_flags: SS_DISABLE, - // Workaround for bug in MacOS implementation of sigaltstack + // Workaround for bug in macOS implementation of sigaltstack // UNIX2003 which returns ENOMEM when disabling a stack while // passing ss_size smaller than MINSIGSTKSZ. According to POSIX // both ss_sp and ss_size should be ignored in this case. diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index c63dd8a47ca..d6e2fed56be 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -144,7 +144,7 @@ pub trait OpenOptionsExt { /// `CreateFile`). /// /// If a _new_ file is created because it does not yet exist and - ///`.create(true)` or `.create_new(true)` are specified, the new file is + /// `.create(true)` or `.create_new(true)` are specified, the new file is /// given the attributes declared with `.attributes()`. /// /// If an _existing_ file is opened with `.create(true).truncate(true)`, its diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs index 1419a4af427..759f055c4b1 100644 --- a/src/libstd/sys/windows/ext/process.rs +++ b/src/libstd/sys/windows/ext/process.rs @@ -104,6 +104,7 @@ pub trait CommandExt { /// Sets the [process creation flags][1] to be passed to `CreateProcess`. /// /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`. + /// /// [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx #[stable(feature = "windows_process_extensions", since = "1.16.0")] fn creation_flags(&mut self, flags: u32) -> &mut process::Command; diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 1afb3728c9d..dfbc1b581ee 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -257,8 +257,13 @@ impl Stdio { // INVALID_HANDLE_VALUE. Stdio::Inherit => { match stdio::get(stdio_id) { - Ok(io) => io.handle().duplicate(0, true, - c::DUPLICATE_SAME_ACCESS), + Ok(io) => { + let io = Handle::new(io.handle()); + let ret = io.duplicate(0, true, + c::DUPLICATE_SAME_ACCESS); + io.into_raw(); + return ret + } Err(..) => Ok(Handle::new(c::INVALID_HANDLE_VALUE)), } } diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index b1a57c349fb..d72e4b4438b 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -22,42 +22,43 @@ use sys::cvt; use sys::handle::Handle; use sys_common::io::read_to_end_uninitialized; -pub struct NoClose(Option<Handle>); - pub enum Output { - Console(NoClose), - Pipe(NoClose), + Console(c::HANDLE), + Pipe(c::HANDLE), } pub struct Stdin { - handle: Output, utf8: Mutex<io::Cursor<Vec<u8>>>, } -pub struct Stdout(Output); -pub struct Stderr(Output); +pub struct Stdout; +pub struct Stderr; pub fn get(handle: c::DWORD) -> io::Result<Output> { let handle = unsafe { c::GetStdHandle(handle) }; if handle == c::INVALID_HANDLE_VALUE { Err(io::Error::last_os_error()) } else if handle.is_null() { - Err(io::Error::new(io::ErrorKind::Other, - "no stdio handle available for this process")) + Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32)) } else { - let ret = NoClose::new(handle); let mut out = 0; match unsafe { c::GetConsoleMode(handle, &mut out) } { - 0 => Ok(Output::Pipe(ret)), - _ => Ok(Output::Console(ret)), + 0 => Ok(Output::Pipe(handle)), + _ => Ok(Output::Console(handle)), } } } -fn write(out: &Output, data: &[u8]) -> io::Result<usize> { - let handle = match *out { - Output::Console(ref c) => c.get().raw(), - Output::Pipe(ref p) => return p.get().write(data), +fn write(handle: c::DWORD, data: &[u8]) -> io::Result<usize> { + let handle = match try!(get(handle)) { + Output::Console(c) => c, + Output::Pipe(p) => { + let handle = Handle::new(p); + let ret = handle.write(data); + handle.into_raw(); + return ret + } }; + // As with stdin on windows, stdout often can't handle writes of large // sizes. For an example, see #14940. For this reason, don't try to // write the entire output buffer on windows. @@ -93,18 +94,20 @@ fn write(out: &Output, data: &[u8]) -> io::Result<usize> { impl Stdin { pub fn new() -> io::Result<Stdin> { - get(c::STD_INPUT_HANDLE).map(|handle| { - Stdin { - handle: handle, - utf8: Mutex::new(Cursor::new(Vec::new())), - } + Ok(Stdin { + utf8: Mutex::new(Cursor::new(Vec::new())), }) } pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - let handle = match self.handle { - Output::Console(ref c) => c.get().raw(), - Output::Pipe(ref p) => return p.get().read(buf), + let handle = match try!(get(c::STD_INPUT_HANDLE)) { + Output::Console(c) => c, + Output::Pipe(p) => { + let handle = Handle::new(p); + let ret = handle.read(buf); + handle.into_raw(); + return ret + } }; let mut utf8 = self.utf8.lock().unwrap(); // Read more if the buffer is empty @@ -125,11 +128,9 @@ impl Stdin { Ok(utf8) => utf8.into_bytes(), Err(..) => return Err(invalid_encoding()), }; - if let Output::Console(_) = self.handle { - if let Some(&last_byte) = data.last() { - if last_byte == CTRL_Z { - data.pop(); - } + if let Some(&last_byte) = data.last() { + if last_byte == CTRL_Z { + data.pop(); } } *utf8 = Cursor::new(data); @@ -158,11 +159,11 @@ impl<'a> Read for &'a Stdin { impl Stdout { pub fn new() -> io::Result<Stdout> { - get(c::STD_OUTPUT_HANDLE).map(Stdout) + Ok(Stdout) } pub fn write(&self, data: &[u8]) -> io::Result<usize> { - write(&self.0, data) + write(c::STD_OUTPUT_HANDLE, data) } pub fn flush(&self) -> io::Result<()> { @@ -172,11 +173,11 @@ impl Stdout { impl Stderr { pub fn new() -> io::Result<Stderr> { - get(c::STD_ERROR_HANDLE).map(Stderr) + Ok(Stderr) } pub fn write(&self, data: &[u8]) -> io::Result<usize> { - write(&self.0, data) + write(c::STD_ERROR_HANDLE, data) } pub fn flush(&self) -> io::Result<()> { @@ -197,27 +198,12 @@ impl io::Write for Stderr { } } -impl NoClose { - fn new(handle: c::HANDLE) -> NoClose { - NoClose(Some(Handle::new(handle))) - } - - fn get(&self) -> &Handle { self.0.as_ref().unwrap() } -} - -impl Drop for NoClose { - fn drop(&mut self) { - self.0.take().unwrap().into_raw(); - } -} - impl Output { - pub fn handle(&self) -> &Handle { - let nc = match *self { - Output::Console(ref c) => c, - Output::Pipe(ref c) => c, - }; - nc.0.as_ref().unwrap() + pub fn handle(&self) -> c::HANDLE { + match *self { + Output::Console(c) => c, + Output::Pipe(c) => c, + } } } |
