Skip to content

Refactor Windows stdio and remove stdin double buffering #58454

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 24, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ pub use self::stdio::{_print, _eprint};
#[doc(no_inline, hidden)]
pub use self::stdio::{set_panic, set_print};

// Used inside the standard library for panic output.
pub(crate) use self::stdio::stderr_raw;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offending line (unused import)


pub mod prelude;
mod buffered;
mod cursor;
Expand Down
8 changes: 6 additions & 2 deletions src/libstd/io/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ struct StdoutRaw(stdio::Stdout);
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stdio::stderr_raw` function.
struct StderrRaw(stdio::Stderr);
///
/// Not exposed, but used inside the standard library for panic output.
pub(crate) struct StderrRaw(stdio::Stderr);

/// Constructs a new raw handle to the standard input of this process.
///
Expand Down Expand Up @@ -61,7 +63,9 @@ fn stdout_raw() -> io::Result<StdoutRaw> { stdio::Stdout::new().map(StdoutRaw) }
///
/// The returned handle has no external synchronization or buffering layered on
/// top.
fn stderr_raw() -> io::Result<StderrRaw> { stdio::Stderr::new().map(StderrRaw) }
///
/// Not exposed, but used inside the standard library for panic output.
pub(crate) fn stderr_raw() -> io::Result<StderrRaw> { stdio::Stderr::new().map(StderrRaw) }

impl Read for StdinRaw {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
Expand Down
29 changes: 11 additions & 18 deletions src/libstd/sys/cloudabi/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ impl Stdin {
pub fn new() -> io::Result<Stdin> {
Ok(Stdin(()))
}
}

pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
impl io::Read for Stdin {
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
Ok(0)
}
}
Expand All @@ -19,15 +21,17 @@ impl Stdout {
pub fn new() -> io::Result<Stdout> {
Ok(Stdout(()))
}
}

pub fn write(&self, _: &[u8]) -> io::Result<usize> {
impl io::Write for Stdout {
fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
Err(io::Error::new(
io::ErrorKind::BrokenPipe,
"Stdout is not connected to any output in this environment",
))
}

pub fn flush(&self) -> io::Result<()> {
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
Expand All @@ -36,29 +40,18 @@ impl Stderr {
pub fn new() -> io::Result<Stderr> {
Ok(Stderr(()))
}
}

pub fn write(&self, _: &[u8]) -> io::Result<usize> {
impl io::Write for Stderr {
fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
Err(io::Error::new(
io::ErrorKind::BrokenPipe,
"Stderr is not connected to any output in this environment",
))
}

pub fn flush(&self) -> io::Result<()> {
Ok(())
}
}

// FIXME: right now this raw stderr handle is used in a few places because
// std::io::stderr_raw isn't exposed, but once that's exposed this impl
// should go away
impl io::Write for Stderr {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
Stderr::write(self, data)
}

fn flush(&mut self) -> io::Result<()> {
Stderr::flush(self)
Ok(())
}
}

Expand Down
37 changes: 15 additions & 22 deletions src/libstd/sys/redox/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,48 @@ pub struct Stderr(());

impl Stdin {
pub fn new() -> io::Result<Stdin> { Ok(Stdin(())) }
}

pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
impl io::Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let fd = FileDesc::new(0);
let ret = fd.read(data);
let ret = fd.read(buf);
fd.into_raw();
ret
}
}

impl Stdout {
pub fn new() -> io::Result<Stdout> { Ok(Stdout(())) }
}

pub fn write(&self, data: &[u8]) -> io::Result<usize> {
impl io::Write for Stdout {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let fd = FileDesc::new(1);
let ret = fd.write(data);
let ret = fd.write(buf);
fd.into_raw();
ret
}

pub fn flush(&self) -> io::Result<()> {
fn flush(&mut self) -> io::Result<()> {
cvt(syscall::fsync(1)).and(Ok(()))
}
}

impl Stderr {
pub fn new() -> io::Result<Stderr> { Ok(Stderr(())) }
}

pub fn write(&self, data: &[u8]) -> io::Result<usize> {
impl io::Write for Stderr {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let fd = FileDesc::new(2);
let ret = fd.write(data);
let ret = fd.write(buf);
fd.into_raw();
ret
}

pub fn flush(&self) -> io::Result<()> {
cvt(syscall::fsync(2)).and(Ok(()))
}
}

// FIXME: right now this raw stderr handle is used in a few places because
// std::io::stderr_raw isn't exposed, but once that's exposed this impl
// should go away
impl io::Write for Stderr {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
Stderr::write(self, data)
}

fn flush(&mut self) -> io::Result<()> {
Stderr::flush(self)
cvt(syscall::fsync(2)).and(Ok(()))
}
}

Expand All @@ -67,5 +60,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;

pub fn panic_output() -> Option<impl io::Write> {
Stderr::new().ok()
io::stderr_raw().ok()
}
31 changes: 12 additions & 19 deletions src/libstd/sys/sgx/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,39 @@ fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R {

impl Stdin {
pub fn new() -> io::Result<Stdin> { Ok(Stdin(())) }
}

pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
with_std_fd(abi::FD_STDIN, |fd| fd.read(data))
impl io::Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
with_std_fd(abi::FD_STDIN, |fd| fd.read(buf))
}
}

impl Stdout {
pub fn new() -> io::Result<Stdout> { Ok(Stdout(())) }
}

pub fn write(&self, data: &[u8]) -> io::Result<usize> {
with_std_fd(abi::FD_STDOUT, |fd| fd.write(data))
impl io::Write for Stdout {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
with_std_fd(abi::FD_STDOUT, |fd| fd.write(buf))
}

pub fn flush(&self) -> io::Result<()> {
fn flush(&mut self) -> io::Result<()> {
with_std_fd(abi::FD_STDOUT, |fd| fd.flush())
}
}

impl Stderr {
pub fn new() -> io::Result<Stderr> { Ok(Stderr(())) }

pub fn write(&self, data: &[u8]) -> io::Result<usize> {
with_std_fd(abi::FD_STDERR, |fd| fd.write(data))
}

pub fn flush(&self) -> io::Result<()> {
with_std_fd(abi::FD_STDERR, |fd| fd.flush())
}
}

// FIXME: right now this raw stderr handle is used in a few places because
// std::io::stderr_raw isn't exposed, but once that's exposed this impl
// should go away
impl io::Write for Stderr {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
Stderr::write(self, data)
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
with_std_fd(abi::FD_STDERR, |fd| fd.write(buf))
}

fn flush(&mut self) -> io::Result<()> {
Stderr::flush(self)
with_std_fd(abi::FD_STDERR, |fd| fd.flush())
}
}

Expand Down
37 changes: 15 additions & 22 deletions src/libstd/sys/unix/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,48 @@ pub struct Stderr(());

impl Stdin {
pub fn new() -> io::Result<Stdin> { Ok(Stdin(())) }
}

pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
impl io::Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let fd = FileDesc::new(libc::STDIN_FILENO);
let ret = fd.read(data);
let ret = fd.read(buf);
fd.into_raw(); // do not close this FD
ret
}
}

impl Stdout {
pub fn new() -> io::Result<Stdout> { Ok(Stdout(())) }
}

pub fn write(&self, data: &[u8]) -> io::Result<usize> {
impl io::Write for Stdout {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let fd = FileDesc::new(libc::STDOUT_FILENO);
let ret = fd.write(data);
let ret = fd.write(buf);
fd.into_raw(); // do not close this FD
ret
}

pub fn flush(&self) -> io::Result<()> {
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}

impl Stderr {
pub fn new() -> io::Result<Stderr> { Ok(Stderr(())) }
}

pub fn write(&self, data: &[u8]) -> io::Result<usize> {
impl io::Write for Stderr {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let fd = FileDesc::new(libc::STDERR_FILENO);
let ret = fd.write(data);
let ret = fd.write(buf);
fd.into_raw(); // do not close this FD
ret
}

pub fn flush(&self) -> io::Result<()> {
Ok(())
}
}

// FIXME: right now this raw stderr handle is used in a few places because
// std::io::stderr_raw isn't exposed, but once that's exposed this impl
// should go away
impl io::Write for Stderr {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
Stderr::write(self, data)
}

fn flush(&mut self) -> io::Result<()> {
Stderr::flush(self)
Ok(())
}
}

Expand All @@ -67,5 +60,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;

pub fn panic_output() -> Option<impl io::Write> {
Stderr::new().ok()
io::stderr_raw().ok()
}
35 changes: 16 additions & 19 deletions src/libstd/sys/wasm/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,27 @@ impl Stdin {
pub fn new() -> io::Result<Stdin> {
Ok(Stdin)
}
}

pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
Ok(ReadSysCall::perform(0, data))
impl io::Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
Ok(ReadSysCall::perform(0, buf))
}
}

impl Stdout {
pub fn new() -> io::Result<Stdout> {
Ok(Stdout)
}
}

pub fn write(&self, data: &[u8]) -> io::Result<usize> {
WriteSysCall::perform(1, data);
Ok(data.len())
impl io::Write for Stdout {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
WriteSysCall::perform(1, buf);
Ok(buf.len())
}

pub fn flush(&self) -> io::Result<()> {
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
Expand All @@ -34,23 +38,16 @@ impl Stderr {
pub fn new() -> io::Result<Stderr> {
Ok(Stderr)
}

pub fn write(&self, data: &[u8]) -> io::Result<usize> {
WriteSysCall::perform(2, data);
Ok(data.len())
}

pub fn flush(&self) -> io::Result<()> {
Ok(())
}
}

impl io::Write for Stderr {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
(&*self).write(data)
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
WriteSysCall::perform(2, buf);
Ok(buf.len())
}

fn flush(&mut self) -> io::Result<()> {
(&*self).flush()
Ok(())
}
}

Expand All @@ -62,7 +59,7 @@ pub fn is_ebadf(_err: &io::Error) -> bool {

pub fn panic_output() -> Option<impl io::Write> {
if cfg!(feature = "wasm_syscall") {
Stderr::new().ok()
io::stderr_raw().ok()
} else {
None
}
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/sys/windows/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,9 @@ impl Stdio {
// should still be unavailable so propagate the
// INVALID_HANDLE_VALUE.
Stdio::Inherit => {
match stdio::get(stdio_id) {
match stdio::get_handle(stdio_id) {
Ok(io) => {
let io = Handle::new(io.handle());
let io = Handle::new(io);
let ret = io.duplicate(0, true,
c::DUPLICATE_SAME_ACCESS);
io.into_raw();
Expand Down
Loading