Skip to content

Commit b652bbc

Browse files
committed
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
1 parent df4c0b8 commit b652bbc

File tree

4 files changed

+19
-10
lines changed

4 files changed

+19
-10
lines changed

src/librustuv/tty.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,22 @@ impl TtyWatcher {
3030
pub fn new(loop_: &Loop, fd: libc::c_int, readable: bool)
3131
-> Result<TtyWatcher, UvError>
3232
{
33-
let handle = UvHandle::alloc(None::<TtyWatcher>, uvll::UV_TTY);
33+
// libuv may succeed in giving us a handle (via uv_tty_init), but if the
34+
// handle isn't actually connected to a terminal there are frequently
35+
// many problems in using it with libuv. To get around this, always
36+
// return a failure if the specified file descriptor isn't actually a
37+
// TTY.
38+
//
39+
// Related:
40+
// - https://github.com/joyent/libuv/issues/982
41+
// - https://github.com/joyent/libuv/issues/988
42+
if unsafe { uvll::guess_handle(fd) != uvll::UV_TTY as libc::c_int } {
43+
return Err(UvError(uvll::EBADF));
44+
}
3445

46+
// If this file descriptor is indeed guessed to be a tty, then go ahead
47+
// with attempting to open it as a tty.
48+
let handle = UvHandle::alloc(None::<TtyWatcher>, uvll::UV_TTY);
3549
match unsafe {
3650
uvll::uv_tty_init(loop_.handle, handle, fd as libc::c_int,
3751
readable as libc::c_int)
@@ -86,10 +100,6 @@ impl RtioTTY for TtyWatcher {
86100
n => Err(uv_error_to_io_error(UvError(n)))
87101
}
88102
}
89-
90-
fn isatty(&self) -> bool {
91-
unsafe { uvll::guess_handle(self.fd) == uvll::UV_TTY as libc::c_int }
92-
}
93103
}
94104

95105
impl UvHandle<uvll::uv_tty_t> for TtyWatcher {

src/librustuv/uvll.rs

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub mod errors {
5454
pub static EPIPE: c_int = -4048;
5555
pub static ECONNABORTED: c_int = -4080;
5656
pub static ECANCELED: c_int = -4082;
57+
pub static EBADF: c_int = -4084;
5758
}
5859
#[cfg(not(windows))]
5960
pub mod errors {
@@ -67,6 +68,7 @@ pub mod errors {
6768
pub static EPIPE: c_int = -libc::EPIPE;
6869
pub static ECONNABORTED: c_int = -libc::ECONNABORTED;
6970
pub static ECANCELED : c_int = -libc::ECANCELED;
71+
pub static EBADF : c_int = -libc::EBADF;
7072
}
7173

7274
pub static PROCESS_SETUID: c_int = 1 << 0;

src/libstd/rt/io/stdio.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -277,12 +277,10 @@ impl StdWriter {
277277
}
278278
}
279279

280-
/// Returns whether this tream is attached to a TTY instance or not.
281-
///
282-
/// This is similar to libc's isatty() function
280+
/// Returns whether this stream is attached to a TTY instance or not.
283281
pub fn isatty(&self) -> bool {
284282
match self.inner {
285-
TTY(ref tty) => tty.isatty(),
283+
TTY(*) => true,
286284
File(*) => false,
287285
}
288286
}

src/libstd/rt/rtio.rs

-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,6 @@ pub trait RtioTTY {
222222
fn write(&mut self, buf: &[u8]) -> Result<(), IoError>;
223223
fn set_raw(&mut self, raw: bool) -> Result<(), IoError>;
224224
fn get_winsize(&mut self) -> Result<(int, int), IoError>;
225-
fn isatty(&self) -> bool;
226225
}
227226

228227
pub trait PausibleIdleCallback {

0 commit comments

Comments
 (0)