-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Docs on safety of BufWriter are misleading #136025
Comments
Related: #98338 |
They address two different kinds of problems.
|
Yes. I think File API/docs make this clear. I think BufWriter is somewhat misleading. In my scenario the OS has reported an error to the application. The application has followed the docs on BufWriter, but has not seen that error and has lost data as a consequence. |
Dropping a It's true that, *if *you want to call |
It's unclear to me whether you care about durability or about error reporting here. If your goal is durability then you need If you don't need durability but still want to report errors (which is kind of weird, since in this case you'd also miss writeback errors after closing a file...) then we could add a |
Fair question. To be awkward, there is a tradeoff between speed and correctness and ergonomics. I think ergonomics could be improved with no loss of performance. Or: there is a class of failure that isn't visible without an fsync. But there is a class of failure that is and we miss that opportunity. (Yes, my users are using NFS with async - docs and tests indicate sync on close happens.) https://github.com/pola-rs/polars/blob/1993d59c31ca5632f2f8fbdd7af413eeafac6e69/crates/polars-python/src/dataframe/io.rs#L480 as a example from broader ecosystem. This pattern is both common and I think encouraged by current docs. Flush is called correctly somewhere, then close happens on drop. Maybe I am just flawed in expectation: I generally expect Rust error handling to stick it in my face and make sure I have dealt with it, compiler enforcing that I have done so. The underlying decision to hide errors from close makes this one counterintuitive. Close docs do say it returns errors and that these can indicate failure to write. |
No, not really. It's just that on NFS with cto specifically close also acts as fsync, with all the performance penalties. You get the error reporting of fsync at the price of fsync. If you're saying "if we already paid the cost in this case, we might as well surface an error", then yeah, ok. But that's just nice-to-have diagnostics, not guaranteed behavior on which you can build reliable applications.
If you never called fsync then, generically, close is allowed to do nothing and defer all the work, which means deferring all the IO errors to where the program cannot see them. So by closing without sync you already told the OS you don't care about errors here, best effort is enough. Rust piggybacks on your signaled intent here.
Well, |
How about master...rgr21:rust:patch-1 ? |
Location
rust/library/std/src/io/buffered/bufwriter.rs
Line 9 in 8231e85
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.
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.
rust/library/std/src/io/buffered/bufwriter.rs
Line 9 in 8231e85
This really advertises itself for the use case
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
to avoid risk of silent data loss that is otherwise unobservable to the application.
I propose changing the wording at
rust/library/std/src/io/buffered/bufwriter.rs
Line 21 in 8231e85
The text was updated successfully, but these errors were encountered: