Docs on safety of BufWriter are misleading
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Location
Summary
This one is long winded. Sorry. A reader may decide this represents an actual code bug. I believe it is at least a documentation bug. I may just be rediscovering something every other programmer already knows.
let mut file = std::fs::File::create("test")?;
file.write_all(b"Hello, world!")?;
file.flush()?; // This does nothing. It is implemented as return Ok()
file.sync_all()?; // This issues an fsync
drop(file); // Close happens here. Docs correctly say that errors are ignored, sync_all *must* have happened to force the fsync.
In my scenario I am writing a file to an NFS mount from Linux. The syscalls are of the pattern open+write+write+...+close.
Close can fail, and that can prevent data from previous writes (which reported success) from being actually saved. I have no way of seeing the output of close. So I need to call sync_all, giving me a safe open+write+write+...+fsync+close.
/// It can be excessively inefficient to work directly with something that
/// implements [Write]. [...]
///
///BufWriter<W>can improve the speed of programs that make small and
/// repeated write calls to the same file or network socket. [...]
///
/// It is critical to call [flush] beforeBufWriter<W>is dropped. Though
/// dropping will attempt to flush the contents of the buffer, any errors
/// that happen in the process of dropping will be ignored. Calling [flush]
/// ensures that the buffer is empty and thus dropping will not even attempt
/// file operations.
This really advertises itself for the use case
let mut buf = BufWriter::new(std::fs::File::create("test")?)
and then gives guidance on how to use it safely. This talks about errors during drop being lost (correct), says that calling flush is critical (true, but in a misleading way as the call to the inner file.flush is pointless). It does talk about files, not any old Write, steering me further towards madness.
Because I need to call
buf.into_inner()?.sync_all()?;
to avoid risk of silent data loss that is otherwise unobservable to the application.
I propose changing the wording at https://github.com/rust-lang/rust/blob/8231e8599e238ff4e717639bd68c6abb8579fe8d/library/std/src/io/buffered/bufwriter.rs#L21 to indicate that flush is necessary but not sufficient, and perhaps also adding as an example use of into_inner().
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read the documentation comments around lines 9-21 of library/std/src/io/buffered/bufwriter.rs, focusing on the guidance about flush during drop. Revise the wording to explain that flush is necessary but not sufficient for safely persisting file data, and consider the proposed into_inner().sync_all() example. Done means the documentation no longer implies that flush alone handles errors from closing or persisting the underlying file.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100