-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Do we need to clarify the fsync() close() Unix-ism? #42619
Comments
Some older threads on this:
I would argue this ticket is probably a duplicate of that last one. |
Thanks; definitely a duplicate of #32255 I'll continue the discussion there. |
(Uh, how does one mark duplicates on Github?) |
Just closing is the norm here -- we don't have a label or anything like that. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I was doing a little investigation of how/when we close(2) files. This is done in impl Drop for FileDesc, libstd/sys/unix/fd.rs.
This is of course fine. In addition, I was wondering if Rust needs to expose the close() call in the public API, so people could actually check for errors when closing files, and per Unix lore, be safe when closing files on NFS yields an error.
Pretty much every API which wraps close(2) has run into the same issue. The links provided in the comments in the implementation for Glib's g_close() are enlightening, particularly this one. Summary:
I think there are two cases to consider:
People recommend doing fsync() before close() if you really care about the bits being on the disk. This makes sense; fsync() means that both file data and its metadata are written out. The question is whether a successful fsync() means that we can pretty much ignore the result of close().
My next question was about what the kernel is actually doing. On Linux, close() is implemented here:
That
__close_fd()
is here:And
filp_close()
is the one that actually calls file system implementations:On Linux, the only thing (outside of EBADF) that can cause close() to return an error is a file system's flush() returning an error... or EINTR from a signal.
I then looked for which file systems implement
f_op->flush()
. It's only afs, cifs, ecryptfs, exofs, fuse, nfs. And on nfs's implementation, it just calls vfs_flush(), which calls underlying_filesystem->fsync(). Fuse's is hairier, as it actually depends on the implementing process. I didn't look at the others.Also, I have no idea of what other operating systems do!
I think we could have a recommendation to call File.sync_all() for really important, user's data. I am not yet sure if we should export close() in the File API, as I cannot answer "is successful fsync() then close() enough for the safety of the user's data" yet :(
Comments are appreciated.
The text was updated successfully, but these errors were encountered: