diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-11-07 15:24:30 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-11-10 01:37:11 -0800 |
| commit | b652bbc6700e36c9ad80105c89d7fc2e3afec111 (patch) | |
| tree | d204a6217cfb8dbc41fdc44346a779ee60665924 | |
| parent | df4c0b8e4349d50f317553de5a47d0cd56cdc227 (diff) | |
| download | rust-b652bbc6700e36c9ad80105c89d7fc2e3afec111.tar.gz rust-b652bbc6700e36c9ad80105c89d7fc2e3afec111.zip | |
Fall back from uv tty instances more aggressively
It appears that uv's support for interacting with a stdio stream as a tty when it's actually a pipe is pretty problematic. To get around this, promote a check to see if the stream is a tty to the top of the tty constructor, and bail out quickly if it's not identified as a tty. Closes #10237
| -rw-r--r-- | src/librustuv/tty.rs | 20 | ||||
| -rw-r--r-- | src/librustuv/uvll.rs | 2 | ||||
| -rw-r--r-- | src/libstd/rt/io/stdio.rs | 6 | ||||
| -rw-r--r-- | src/libstd/rt/rtio.rs | 1 |
4 files changed, 19 insertions, 10 deletions
diff --git a/src/librustuv/tty.rs b/src/librustuv/tty.rs index 04e406ce987..4853973f1a3 100644 --- a/src/librustuv/tty.rs +++ b/src/librustuv/tty.rs @@ -30,8 +30,22 @@ impl TtyWatcher { pub fn new(loop_: &Loop, fd: libc::c_int, readable: bool) -> Result<TtyWatcher, UvError> { - let handle = UvHandle::alloc(None::<TtyWatcher>, uvll::UV_TTY); + // libuv may succeed in giving us a handle (via uv_tty_init), but if the + // handle isn't actually connected to a terminal there are frequently + // many problems in using it with libuv. To get around this, always + // return a failure if the specified file descriptor isn't actually a + // TTY. + // + // Related: + // - https://github.com/joyent/libuv/issues/982 + // - https://github.com/joyent/libuv/issues/988 + if unsafe { uvll::guess_handle(fd) != uvll::UV_TTY as libc::c_int } { + return Err(UvError(uvll::EBADF)); + } + // If this file descriptor is indeed guessed to be a tty, then go ahead + // with attempting to open it as a tty. + let handle = UvHandle::alloc(None::<TtyWatcher>, uvll::UV_TTY); match unsafe { uvll::uv_tty_init(loop_.handle, handle, fd as libc::c_int, readable as libc::c_int) @@ -86,10 +100,6 @@ impl RtioTTY for TtyWatcher { n => Err(uv_error_to_io_error(UvError(n))) } } - - fn isatty(&self) -> bool { - unsafe { uvll::guess_handle(self.fd) == uvll::UV_TTY as libc::c_int } - } } impl UvHandle<uvll::uv_tty_t> for TtyWatcher { diff --git a/src/librustuv/uvll.rs b/src/librustuv/uvll.rs index d009201e840..58d182a22c3 100644 --- a/src/librustuv/uvll.rs +++ b/src/librustuv/uvll.rs @@ -54,6 +54,7 @@ pub mod errors { pub static EPIPE: c_int = -4048; pub static ECONNABORTED: c_int = -4080; pub static ECANCELED: c_int = -4082; + pub static EBADF: c_int = -4084; } #[cfg(not(windows))] pub mod errors { @@ -67,6 +68,7 @@ pub mod errors { pub static EPIPE: c_int = -libc::EPIPE; pub static ECONNABORTED: c_int = -libc::ECONNABORTED; pub static ECANCELED : c_int = -libc::ECANCELED; + pub static EBADF : c_int = -libc::EBADF; } pub static PROCESS_SETUID: c_int = 1 << 0; diff --git a/src/libstd/rt/io/stdio.rs b/src/libstd/rt/io/stdio.rs index d33821a34b1..674b34639bc 100644 --- a/src/libstd/rt/io/stdio.rs +++ b/src/libstd/rt/io/stdio.rs @@ -277,12 +277,10 @@ impl StdWriter { } } - /// Returns whether this tream is attached to a TTY instance or not. - /// - /// This is similar to libc's isatty() function + /// Returns whether this stream is attached to a TTY instance or not. pub fn isatty(&self) -> bool { match self.inner { - TTY(ref tty) => tty.isatty(), + TTY(*) => true, File(*) => false, } } diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs index 1e12da8645c..d623914cdad 100644 --- a/src/libstd/rt/rtio.rs +++ b/src/libstd/rt/rtio.rs @@ -222,7 +222,6 @@ pub trait RtioTTY { fn write(&mut self, buf: &[u8]) -> Result<(), IoError>; fn set_raw(&mut self, raw: bool) -> Result<(), IoError>; fn get_winsize(&mut self) -> Result<(int, int), IoError>; - fn isatty(&self) -> bool; } pub trait PausibleIdleCallback { |
