From 6ea8222913de9f628edac825c1f3d599762aa96f Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 7 Mar 2016 16:35:37 -0500 Subject: [PATCH 1/2] 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 --- src/libstd/io/buffered.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index ccebf3682c217..bc26b63c153c8 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -762,8 +762,10 @@ impl Write for LineWriter { 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), From c516335815c0bda958d81ca5f964473c212e5a4d Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 7 Mar 2016 18:00:22 -0500 Subject: [PATCH 2/2] Add test case for #32085 --- src/libstd/io/buffered.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index bc26b63c153c8..08877fe9744c9 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -984,6 +984,34 @@ mod tests { assert_eq!(v, []); } + #[test] + fn test_line_buffer_fail_flush() { + // Issue #32085 + struct FailFlushWriter<'a>(&'a mut Vec); + + impl<'a> Write for FailFlushWriter<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { + 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());