Skip to content

Commit

Permalink
Auto merge of #32107 - Stebalien:partial-write, r=alexcrichton
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Mar 10, 2016
2 parents 4b87655 + c516335 commit c1fb50f
Showing 1 changed file with 32 additions and 2 deletions.
34 changes: 32 additions & 2 deletions src/libstd/io/buffered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -982,6 +984,34 @@ mod tests {
assert_eq!(v, []);
}

#[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());
Expand Down

0 comments on commit c1fb50f

Please sign in to comment.