about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-03-13 09:27:17 -0700
committerbors <bors@rust-lang.org>2016-03-13 09:27:17 -0700
commitce943eb369c9bdd0aef4917675e515f39f3b4a1e (patch)
treeb66a3a32cd6198ffea1bbf50afeba20092c5ca2e /src/libstd/sys
parent1c8b245928c3f2463b45fbddd862a0a70882d087 (diff)
parentbd80a53407e15f13ce50a07642491680010fa090 (diff)
downloadrust-ce943eb369c9bdd0aef4917675e515f39f3b4a1e.tar.gz
rust-ce943eb369c9bdd0aef4917675e515f39f3b4a1e.zip
Auto merge of #32184 - ollie27:win_stdout, r=alexcrichton
Fixup stout/stderr on Windows

WriteConsoleW can fail if called with a large buffer so we need to slice
any stdout/stderr output.
However the current slicing has a few problems:
 1. It slices by byte but still expects valid UTF-8.
 2. The slicing happens even when not outputting to a console.
 3. panic! output is not sliced.

This fixes these issues by moving the slice to right before
WriteConsoleW and slicing on a char boundary.
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/windows/stdio.rs23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs
index 5883904c21d..0a0851ffac3 100644
--- a/src/libstd/sys/windows/stdio.rs
+++ b/src/libstd/sys/windows/stdio.rs
@@ -13,6 +13,7 @@
 use prelude::v1::*;
 use io::prelude::*;
 
+use cmp;
 use io::{self, Cursor};
 use ptr;
 use str;
@@ -58,10 +59,24 @@ fn write(out: &Output, data: &[u8]) -> io::Result<usize> {
         Output::Console(ref c) => c.get().raw(),
         Output::Pipe(ref p) => return p.get().write(data),
     };
-    let utf16 = match str::from_utf8(data).ok() {
-        Some(utf8) => utf8.encode_utf16().collect::<Vec<u16>>(),
-        None => return Err(invalid_encoding()),
+    // As with stdin on windows, stdout often can't handle writes of large
+    // sizes. For an example, see #14940. For this reason, don't try to
+    // write the entire output buffer on windows.
+    //
+    // For some other references, it appears that this problem has been
+    // encountered by others [1] [2]. We choose the number 8K just because
+    // libuv does the same.
+    //
+    // [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232
+    // [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html
+    const OUT_MAX: usize = 8192;
+    let len = cmp::min(data.len(), OUT_MAX);
+    let utf8 = match str::from_utf8(&data[..len]) {
+        Ok(s) => s,
+        Err(ref e) if e.valid_up_to() == 0 => return Err(invalid_encoding()),
+        Err(e) => str::from_utf8(&data[..e.valid_up_to()]).unwrap(),
     };
+    let utf16 = utf8.encode_utf16().collect::<Vec<u16>>();
     let mut written = 0;
     try!(cvt(unsafe {
         c::WriteConsoleW(handle,
@@ -74,7 +89,7 @@ fn write(out: &Output, data: &[u8]) -> io::Result<usize> {
     // FIXME if this only partially writes the utf16 buffer then we need to
     //       figure out how many bytes of `data` were actually written
     assert_eq!(written as usize, utf16.len());
-    Ok(data.len())
+    Ok(utf8.len())
 }
 
 impl Stdin {