about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-06-16 15:11:13 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-06-16 22:12:15 -0700
commitd400563e179b9836304d55f1eaee9ce33f54fb7f (patch)
tree8716c917713ce34fff37777964b7f7cce734b849
parent09967665eaa5ca3d259f0f59ef26c8d236bf47a7 (diff)
downloadrust-d400563e179b9836304d55f1eaee9ce33f54fb7f.tar.gz
rust-d400563e179b9836304d55f1eaee9ce33f54fb7f.zip
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
-rw-r--r--src/libstd/io/stdio.rs19
-rw-r--r--src/test/run-pass/issue-14940.rs24
2 files changed, 39 insertions, 4 deletions
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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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());
+    }
+}