Skip to content

Don't return an error after a partial write in LineWriter #32085

Closed

Description

LineWriter can return an error after a partial write if flushing the inner BufWriter fails (

try!(self.inner.flush());
). It should instead return Ok(bytes_written), ignoring the error.

OLD REPORT:

I originally thought this problem was systematic so I audited stdlib. Apparently it isn't... See below.

The write trait guarantees:

If an error is returned then no bytes in the buffer were written to this writer.

However, this is violated all over stdlib. For example, if "abc\nde" is written to a LineWriter, the LineWriter could write "abc", try to flush, and then return an error due to a failed flush. However, "abc" has been written violating the spec.

IMO, the solution is to return Ok(amount_written) for partial writes and drop the error (if any). This should be safe because of write's write-xor-error guarantee. If the error was transient, the caller never needs to know. Otherwise, they will will learn of it on the next write.

Here's everything in the stdlib that implements write (and should be audited):

  • Sink in librustdoc/test.rs
  • Sink in libstd/io/util.rs
  • &'a mut W in libstd/io/impls.rs
  • Box<W> in libstd/io/impls.rs
  • &'a mut [u8] in libstd/io/impls.rs
  • Vec<u8> in libstd/io/impls.rs
  • Cursor<&'a mut [u8]> in libstd/io/cursor.rs
  • Cursor<Vec<u8>> in libstd/io/cursor.rs
  • Cursor<Box<[u8]>> in libstd/io/cursor.rs
  • StdoutRaw in libstd/io/stdio.rs
  • StderrRaw in libstd/io/stdio.rs
  • Maybe<W> in libstd/io/stdio.rs
  • Stdout in libstd/io/stdio.rs
  • StdoutLock<'a> in libstd/io/stdio.rs
  • Stderr in libstd/io/stdio.rs
  • StderrLock<'a> in libstd/io/stdio.rs
  • BufWriter<W> in libstd/io/buffered.rs
  • LineWriter<W> in libstd/io/buffered.rs (buggy)
  • Broadcast<T, U> in libstd/io/mod.rs (buggy but unfixable and deprecated).
  • TcpStream in libstd/net/tcp.rs
  • &'a TcpStream in libstd/net/tcp.rs
  • Stderr in libstd/sys/unix/stdio.rs
  • Stderr in libstd/sys/windows/stdio.rs (panics on partial write)
  • ChildStdin in libstd/process.rs
  • File in libstd/fs.rs
  • &'a File in libstd/fs.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions