about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-03-10 11:56:29 -0800
committerbors <bors@rust-lang.org>2016-03-10 11:56:29 -0800
commitc1fb50f5d377a41dd5833e4621e9a14879647503 (patch)
tree1267b25a66c4ea40ef1c4e0f268f852291bc236d /src/libstd
parent4b87655e69a6d07f03b104caaec80a042ad40bf1 (diff)
parentc516335815c0bda958d81ca5f964473c212e5a4d (diff)
downloadrust-c1fb50f5d377a41dd5833e4621e9a14879647503.tar.gz
rust-c1fb50f5d377a41dd5833e4621e9a14879647503.zip
Auto merge of #32107 - Stebalien:partial-write, r=alexcrichton
Never return an error after a partial write

If LineWriter fails to flush, return the number of bytes written instead
of an error.

Fixes #32085
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/io/buffered.rs34
1 files changed, 32 insertions, 2 deletions
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index ccebf3682c2..08877fe9744 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -762,8 +762,10 @@ impl<W: Write> Write for LineWriter<W> {
         match memchr::memrchr(b'\n', buf) {
             Some(i) => {
                 let n = try!(self.inner.write(&buf[..i + 1]));
-                if n != i + 1 { return Ok(n) }
-                try!(self.inner.flush());
+                if n != i + 1 || self.inner.flush().is_err() {
+                    // Do not return errors on partial writes.
+                    return Ok(n);
+                }
                 self.inner.write(&buf[i + 1..]).map(|i| n + i)
             }
             None => self.inner.write(buf),
@@ -983,6 +985,34 @@ mod tests {
     }
 
     #[test]
+    fn test_line_buffer_fail_flush() {
+        // Issue #32085
+        struct FailFlushWriter<'a>(&'a mut Vec<u8>);
+
+        impl<'a> Write for FailFlushWriter<'a> {
+            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+                self.0.extend_from_slice(buf);
+                Ok(buf.len())
+            }
+            fn flush(&mut self) -> io::Result<()> {
+                Err(io::Error::new(io::ErrorKind::Other, "flush failed"))
+            }
+        }
+
+        let mut buf = Vec::new();
+        {
+            let mut writer = LineWriter::new(FailFlushWriter(&mut buf));
+            let to_write = b"abc\ndef";
+            if let Ok(written) = writer.write(to_write) {
+                assert!(written < to_write.len(), "didn't flush on new line");
+                // PASS
+                return;
+            }
+        }
+        assert!(buf.is_empty(), "write returned an error but wrote data");
+    }
+
+    #[test]
     fn test_line_buffer() {
         let mut writer = LineWriter::new(Vec::new());
         writer.write(&[0]).unwrap();