From fb48c55999d182cc08e008025b7e53eed849de1f Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Fri, 27 Sep 2019 19:16:06 +0200 Subject: [PATCH] Change to non-line buffered output if output is not a TTY This matches glibc behavior. This is determined using the `isatty` function on Unixes, and not attempted at all for other operating systems. Fixes #60673. --- src/libstd/io/stdio.rs | 17 +++++++++++++---- src/libstd/sys/cloudabi/stdio.rs | 3 +++ src/libstd/sys/sgx/stdio.rs | 4 ++++ src/libstd/sys/unix/stdio.rs | 5 +++++ src/libstd/sys/vxworks/stdio.rs | 4 ++++ src/libstd/sys/wasi/stdio.rs | 6 ++++++ src/libstd/sys/wasm/stdio.rs | 4 ++++ src/libstd/sys/windows/stdio.rs | 5 +++++ src/libstd/sys/windows/stdio_uwp.rs | 5 +++++ 9 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 43c94219807c2..be0b48ba10e02 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -84,6 +84,11 @@ impl Read for StdinRaw { Initializer::nop() } } +impl StdoutRaw { + fn should_be_line_buffered(&self) -> bool { + self.0.should_be_line_buffered() + } +} impl Write for StdoutRaw { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } @@ -496,9 +501,6 @@ impl fmt::Debug for StdinLock<'_> { /// [`io::stdout`]: fn.stdout.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Stdout { - // FIXME: this should be LineWriter or BufWriter depending on the state of - // stdout (tty or not). Note that if this is not line buffered it - // should also flush-on-panic or some form of flush-on-abort. inner: Arc>>>, } @@ -572,7 +574,14 @@ pub fn stdout() -> Stdout { fn stdout_init() -> Arc>>> { // This must not reentrantly access `INSTANCE` let stdout = match stdout_raw() { - Ok(stdout) => StdioWriter::new(stdout, StdioBufferKind::LineBuffered), + Ok(stdout) => { + let buffering = if stdout.should_be_line_buffered() { + StdioBufferKind::LineBuffered + } else { + StdioBufferKind::Buffered + }; + StdioWriter::new(stdout, buffering) + }, _ => StdioWriter::new_fake(), }; Arc::new(ReentrantMutex::new(RefCell::new(stdout))) diff --git a/src/libstd/sys/cloudabi/stdio.rs b/src/libstd/sys/cloudabi/stdio.rs index 601563c5b1fcb..7ce94820696ca 100644 --- a/src/libstd/sys/cloudabi/stdio.rs +++ b/src/libstd/sys/cloudabi/stdio.rs @@ -21,6 +21,9 @@ impl Stdout { pub fn new() -> io::Result { Ok(Stdout(())) } + pub fn should_be_line_buffered(&self) -> bool { + true + } } impl io::Write for Stdout { diff --git a/src/libstd/sys/sgx/stdio.rs b/src/libstd/sys/sgx/stdio.rs index a575401f5f60d..c423880bc3183 100644 --- a/src/libstd/sys/sgx/stdio.rs +++ b/src/libstd/sys/sgx/stdio.rs @@ -30,6 +30,10 @@ impl io::Read for Stdin { impl Stdout { pub fn new() -> io::Result { Ok(Stdout(())) } + pub fn should_be_line_buffered(&self) -> bool { + // FIXME: Implement me. + true + } } impl io::Write for Stdout { diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index f9b017df24088..2c3bad1711f6a 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -22,6 +22,11 @@ impl io::Read for Stdin { impl Stdout { pub fn new() -> io::Result { Ok(Stdout(())) } + pub fn should_be_line_buffered(&self) -> bool { + unsafe { + libc::isatty(libc::STDOUT_FILENO) != 0 + } + } } impl io::Write for Stdout { diff --git a/src/libstd/sys/vxworks/stdio.rs b/src/libstd/sys/vxworks/stdio.rs index 35f163bbdb10f..46f13b2b47e65 100644 --- a/src/libstd/sys/vxworks/stdio.rs +++ b/src/libstd/sys/vxworks/stdio.rs @@ -20,6 +20,10 @@ impl io::Read for Stdin { impl Stdout { pub fn new() -> io::Result { Ok(Stdout(())) } + pub fn should_be_line_buffered(&self) -> bool { + // FIXME: Implement me. + true + } } impl io::Write for Stdout { diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs index 1d57b9922e599..3e9e3ebbcfa7a 100644 --- a/src/libstd/sys/wasi/stdio.rs +++ b/src/libstd/sys/wasi/stdio.rs @@ -40,6 +40,12 @@ impl Stdout { pub fn flush(&self) -> io::Result<()> { Ok(()) } + + pub fn should_be_line_buffered(&self) -> bool { + // FIXME: Currently there seems to be no way to query whether stdout is + // a tty, `isatty` is not exposed by WASI. + true + } } impl Stderr { diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs index 5a4e4505e93bd..34b8d9caedcf6 100644 --- a/src/libstd/sys/wasm/stdio.rs +++ b/src/libstd/sys/wasm/stdio.rs @@ -30,6 +30,10 @@ impl io::Write for Stdout { fn flush(&mut self) -> io::Result<()> { Ok(()) } + + fn should_be_line_buffered(&self) -> bool { + true + } } impl Stderr { diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index b1e76b3b755da..32156d478b0e5 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -246,6 +246,11 @@ impl Stdout { pub fn new() -> io::Result { Ok(Stdout) } + pub fn should_be_line_buffered(&self) -> bool { + // FIXME: Fill in. I don't know how to check whether output is + // redirected on Windows. + true + } } impl io::Write for Stdout { diff --git a/src/libstd/sys/windows/stdio_uwp.rs b/src/libstd/sys/windows/stdio_uwp.rs index 489d3df28600b..9f5e27722b47d 100644 --- a/src/libstd/sys/windows/stdio_uwp.rs +++ b/src/libstd/sys/windows/stdio_uwp.rs @@ -48,6 +48,11 @@ impl Stdout { pub fn new() -> io::Result { Ok(Stdout) } + pub fn should_be_line_buffered(&self) -> bool { + // FIXME: Fill in. I don't know how to check whether output is + // redirected on Windows. + true + } } impl io::Write for Stdout {