-
Notifications
You must be signed in to change notification settings - Fork 19
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
Make fs::remove_dir_all
race-resistant
#170
Comments
fs::remove_dir_all
race-resistantfs::remove_dir_all
race-resistant
On windows there can be an error if multiple processes have a handle open for a directory object in the tree that's to be deleted and that can't be ignored because it means the directory may not have been deleted. |
I don't think that affects the suggested solution? Returning And on modern versions of Windows, with POSIX delete semantics, any stepping on toes can be mitigated to an extent unless there's an actual lock involved. |
It's worth noting that this could be considered a breaking change: any code that relies on this returning an error when the path does not exist could break. I'm not sure what such code would look like, but if the risk level is deemed to be too high, removing the first match statement in However, that alternate function would not be idempotent. And I'd still consider that behavior to be inconsistent with |
I do think the top dir should report when it's missing, just like the single |
In those cases you wouldn't get NotFound though, you'd get whatever the "handle in use" error is on windows, no? This is an ACP, so I assume it's about providing the guarantee of concurrent idempotence. Which we can't if races can lead to cross-thread interference. |
It's an ACP because it changes the observed runtime behavior of a stable API. Providing some guarantees would be nice, but that is not a requirement as far as I'm concerned. |
Well, the problem statement of this ACP is
To make it usable for that scenario we would have to provide a guarantee, no? Otherwise we'd be sending users to their probabilistic doom. |
We could guarantee the behavior only on some OSs. But regardless, the proposed behavior is, IMO, strictly an improvement over the current behavior. |
Another issue, rust-lang/rust#95925 would change the unix impl to be iterative instead of recursive and wants to open |
Yeah, if it were only that then imo it wouldn't even need an ACP, it could be considered a QoI thing. But I'm not sure if "breaks under current use 1/10 times" to "breaks 1/100 times" (numbers made up) is really an improvement, it might just delay the errors until you're on production. |
Proposal
Problem statement
Currently,
fs::remove_dir_all
will fail if the directory in question does not exist. It will also fail if any descendant fails deletion for any reason, even if that's because it doesn't exist.This means the API is not idempotent, and can fail when multiple threads or processes call it concurrently.
Motivation, use-cases
The current documentation for this function does not directly state the above behavior, instead simply punting to the docs for
fs::remove_file
andfs::remove_dir
.The current behavior is also in stark contrast to
fs::create_dir_all
, which has been race-resistant since 2017:Solution sketches
Change the
remove_dir_all
algorithm to work similarly tocreate_dir_all
:Ok(())
.ErrorKind::NotFound
as if the deletion succeeded.read_dir
andremove_dir
are immediately returned.Links and related work
create_dir_all
race-resistant: rust-lang/rust@db00ba9What happens now?
This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.
The text was updated successfully, but these errors were encountered: