From d400563e179b9836304d55f1eaee9ce33f54fb7f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 16 Jun 2014 15:11:13 -0700 Subject: [PATCH] std: Chunk writing to stdout on windows This just takes a similar approach to reading stdin on windows by artificially limiting the size of the buffers going in and out. Closes #14940 --- src/libstd/io/stdio.rs | 19 +++++++++++++++---- src/test/run-pass/issue-14940.rs | 24 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 src/test/run-pass/issue-14940.rs diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 071480fb5ee..c989dcc3d29 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -31,6 +31,7 @@ use failure::local_stderr; use fmt; use io::{Reader, Writer, IoResult, IoError, OtherIoError, standard_error, EndOfFile, LineBufferedWriter, BufferedReader}; +use iter::Iterator; use kinds::Send; use libc; use option::{Option, Some, None}; @@ -40,7 +41,9 @@ use rt; use rt::local::Local; use rt::task::Task; use rt::rtio::{DontClose, IoFactory, LocalIo, RtioFileStream, RtioTTY}; +use slice::ImmutableVector; use str::StrSlice; +use uint; // And so begins the tale of acquiring a uv handle to a stdio stream on all // platforms in all situations. Our story begins by splitting the world into two @@ -355,10 +358,18 @@ impl StdWriter { impl Writer for StdWriter { fn write(&mut self, buf: &[u8]) -> IoResult<()> { - match self.inner { - TTY(ref mut tty) => tty.write(buf), - File(ref mut file) => file.write(buf), - }.map_err(IoError::from_rtio_error) + // As with stdin on windows, stdout often can't handle writes of large + // sizes. For an example, see #14940. For this reason, chunk the output + // buffer on windows, but on unix we can just write the whole buffer all + // at once. + let max_size = if cfg!(windows) {64 * 1024} else {uint::MAX}; + for chunk in buf.chunks(max_size) { + try!(match self.inner { + TTY(ref mut tty) => tty.write(chunk), + File(ref mut file) => file.write(chunk), + }.map_err(IoError::from_rtio_error)) + } + Ok(()) } } diff --git a/src/test/run-pass/issue-14940.rs b/src/test/run-pass/issue-14940.rs new file mode 100644 index 00000000000..e0a63331e97 --- /dev/null +++ b/src/test/run-pass/issue-14940.rs @@ -0,0 +1,24 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::os; +use std::io::{stdio, Command}; + +fn main() { + let args = os::args(); + if args.len() > 1 { + let mut out = stdio::stdout(); + out.write(['a' as u8, ..128 * 1024]).unwrap(); + } else { + let out = Command::new(args.get(0).as_slice()).arg("child").output(); + let out = out.unwrap(); + assert!(out.status.success()); + } +}