-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Tracking Issue for File lock API #130994
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
Comments
Implement file_lock feature This adds lock(), lock_shared(), try_lock(), try_lock_shared(), and unlock() to File gated behind the file_lock feature flag This is the initial implementation of rust-lang#130994 for Unix and Windows platforms. I will follow it up with an implementation for WASI preview 2
Rollup merge of rust-lang#130999 - cberner:flock_pr, r=joboet Implement file_lock feature This adds lock(), lock_shared(), try_lock(), try_lock_shared(), and unlock() to File gated behind the file_lock feature flag This is the initial implementation of rust-lang#130994 for Unix and Windows platforms. I will follow it up with an implementation for WASI preview 2
Implement file_lock feature This adds lock(), lock_shared(), try_lock(), try_lock_shared(), and unlock() to File gated behind the file_lock feature flag This is the initial implementation of rust-lang#130994 for Unix and Windows platforms. I will follow it up with an implementation for WASI preview 2
apparently not supported on all tier 2 OS: #132921 |
Note that this triggers the This lint fires on the 1.84 beta release, so there might be a number of people who discover this once 1.84 stable goes out. |
It would also be useful to atomically create and lock a file. This is possible on MacOS using the |
While there are more features we may want to add to this in the future, the current state of this seems useful, and works. Stabilizing it would let people who encounter the warnings about a future conflict switch to the new API. Shall we stabilize the current File locking APIs? @rfcbot merge |
Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members: Concerns:
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
I'd like to see some documentation on the lock methods that make it clear that you don't need to manually unlock / that the lock is automatically unlocked when the File is dropped. Right now, that's only documented on the unlock method. Other than that, the documentation could be made a lot less confusing by adding 'by another process' and 'by the same process' in a few places. Right now, the try methods say "Returns false if the file is locked.", but then go on to say it might deadlock if it's already locked. I assume the former should be "locked by another process" and the latter should be "locked by this process". |
The unlock method should document whether it's okay to call it if no locks are held. If calling unlock() is only acceptable when a lock is actually held, this should probably be a Guard style of API. If it's always okay to call unlock(), the current design makes sense to me. |
I'm checking my box with the assumption that these are just small docs changes that we'll do during/before stabilization. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
I've submitted #136288 which should address all the documentation requests. @m-ou-se wrote:
Done.
"process" isn't the granularity here, but I've added clear distinctions about locks acquired via the same handle/descriptor (may deadlock) vs locks acquired via a different handle/descriptor (will block the blocking methods or make the
It's always safe to call (in the Rust sense). I've documented that it'll either return an error or return without doing anything. It'll never explode.
It's always OK (unlike a mutex or similar). It'll never explode. |
…ith-some-locks--would-you-could-you-in-some-docs, r=m-ou-se Improve documentation for file locking Add notes to each method stating that locks get dropped on close. Clarify the return values of the try methods: they're only defined if the lock is held via a *different* file handle/descriptor. That goes along with the documentation that calling them while holding a lock via the *same* file handle/descriptor may deadlock. Document the behavior of unlock if no lock is held. r? `@m-ou-se` (Documentation changes requested in rust-lang#130994 .)
Rollup merge of rust-lang#136288 - joshtriplett:would-you-could-you-with-some-locks--would-you-could-you-in-some-docs, r=m-ou-se Improve documentation for file locking Add notes to each method stating that locks get dropped on close. Clarify the return values of the try methods: they're only defined if the lock is held via a *different* file handle/descriptor. That goes along with the documentation that calling them while holding a lock via the *same* file handle/descriptor may deadlock. Document the behavior of unlock if no lock is held. r? `@m-ou-se` (Documentation changes requested in rust-lang#130994 .)
…locks--would-you-could-you-in-some-docs, r=m-ou-se Improve documentation for file locking Add notes to each method stating that locks get dropped on close. Clarify the return values of the try methods: they're only defined if the lock is held via a *different* file handle/descriptor. That goes along with the documentation that calling them while holding a lock via the *same* file handle/descriptor may deadlock. Document the behavior of unlock if no lock is held. r? `@m-ou-se` (Documentation changes requested in rust-lang/rust#130994 .)
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
@juntyr oh ya, that gives the best of both worlds. I didn't realize that would automatically work with |
Please keep that separate for now. It isn't clear to me that is a good idea, and it is an impl that can be added later after we gain experience with the API. |
Sounds good. I reverted that part of the PR |
This was discussed during the meeting and there was a slightly preference towards a custom error type since that makes it very obvious if the failure was due to a lock already existing or some other I/O error. Also note that currently Windows doesn't turn |
…kingjubilee Change signature of File::try_lock and File::try_lock_shared These methods now return Result<(), TryLockError> instead of Result<bool, Error> to make their use less errorprone These methods are unstable under the "file_lock" feature. The related tracking issue is rust-lang#130999 and this PR changes the signatures as discussed by libs-api: rust-lang#130994 (comment)
…kingjubilee Change signature of File::try_lock and File::try_lock_shared These methods now return Result<(), TryLockError> instead of Result<bool, Error> to make their use less errorprone These methods are unstable under the "file_lock" feature. The related tracking issue is rust-lang#130999 and this PR changes the signatures as discussed by libs-api: rust-lang#130994 (comment)
…kingjubilee Change signature of File::try_lock and File::try_lock_shared These methods now return Result<(), TryLockError> instead of Result<bool, Error> to make their use less errorprone These methods are unstable under the "file_lock" feature. The related tracking issue is rust-lang#130999 and this PR changes the signatures as discussed by libs-api: rust-lang#130994 (comment)
…kingjubilee Change signature of File::try_lock and File::try_lock_shared These methods now return Result<(), TryLockError> instead of Result<bool, Error> to make their use less errorprone These methods are unstable under the "file_lock" feature. The related tracking issue is rust-lang#130999 and this PR changes the signatures as discussed by libs-api: rust-lang#130994 (comment)
Rollup merge of rust-lang#139343 - cberner:filelock_wouldblock, r=workingjubilee Change signature of File::try_lock and File::try_lock_shared These methods now return Result<(), TryLockError> instead of Result<bool, Error> to make their use less errorprone These methods are unstable under the "file_lock" feature. The related tracking issue is rust-lang#130999 and this PR changes the signatures as discussed by libs-api: rust-lang#130994 (comment)
Adding some personal experience. I find the new I can no longer write:
I now have to write
I have to do this in several places in my code base, so it makes sense for me (and probably others) to just add a helper function that is essentially the old API. I think the fundamental problem is that the new API treats blocking as an error when the whole point of the API is to handle blocking gracefully. If the goal is to make the return type more clear, another option is to replace the bool with an |
@det, ya it does make that use case a bit more involved. However, the current API is now consistent with Mutex::try_lock() which seems like a good thing. And it eliminates the possibility of forgetting to check the |
@joshtriplett the |
@cberner thanks, I didn't realize this was matching another API. I guess that makes sense then. |
Nominating for subsequent discussion. |
Speaking for myself: I think the new API is a usability downgrade as well. I think we may want to consider a dedicated two-value enum with |
It is usability downgrade, and it was expected. But it is (supposed to be) more robust by being harder to get confused about and misuse, and harder to not notice during code reviews. Would be nice to have some impl<T> Result<(), TryLockError> {
fn transpose_io(self) -> Result<Result<(), ()>, io::Error> {
// ...
}
} or something like it in stdlib, and have a cake and eat it, but I'm not even sure if it's a terrible idea. Not exactly all that much work to define downstream, though then it requires extension trait. No opinion about an enum. I guess it depends how user-proof it is in practice. Thought intuitively, IMO, not acquiring the lock should be an |
@dpc In practice, one common pattern I've seen try_lock used for is:
Treating |
@rfcbot concern api-is-unergonomic |
Wouldn't this also apply to the existing |
@dpc I'm using this exact pattern in my code (though through BTW. when using this pattern, isn't it easier to just ignore the error (io or already-locked) altogether? if let Ok(guard) = f.try_lock() {
// quiet happy path
return Ok(guard);
}
// locked, or broken disk, or wrong permission, who cares, just print and wait to acquire
info!("Waiting to acquire file lock);
return f.lock(); This assumes that if there's an IO issue during try_lock, it will also happen during lock. |
We talked about this at length in today's @rust-lang/libs-api meeting. We went back and forth about several different API designs. @Amanieu also looked extensively at code search results, and found that a huge number of users of We considered the possibility of Ultimately, the only API we could come to consensus on was There are two interesting ways people want to use
Given all of the above, and with the @rust-lang/libs-api team's apologies for the churn: we'd like to change the API to return |
I'm myself surprised at this discovery. I thought that people will sometimes do that, but I thought the API will be just mildly-error prone. Well, great job actually checking.
What's the rationale for this? It seems functionally it is never a good idea as the would-block and io-error (wrong permissions, etc.) have completely different consequences, and treating them as such seem to only result in higher level issues. Not a tragic mistake, but still probably always incorrect in theoretical sense.
Personally, I'm OK with this. At least not acquiring the lock is always an |
There's quite a lot of code that treats failure to acquire a lock as a fatal error, usually CLI tools that would just report an error to the user. |
No worries, thanks for taking the time to discuss it! I've submitted #140718 which changes the API to return |
@Amanieu @joshtriplett Wait, what happened to the custom error type? That seems like it has all the benefits of |
If they use a lock ... don't they want to wait for it to be released to acquire it? Or are these programs that do not expect to be ran in parallel and use the lock just as a safeguard mechanism? That would make a sense, I guess. |
…kingjubilee Change signature of File::try_lock and File::try_lock_shared These methods now return Result<(), TryLockError> instead of Result<bool, Error> to make their use less errorprone These methods are unstable under the "file_lock" feature. The related tracking issue is rust-lang#130999 and this PR changes the signatures as discussed by libs-api: rust-lang#130994 (comment)
Feature gate:
#![feature(file_lock)]
This is a tracking issue for rust-lang/libs-team#412
This feature exposes advisory file locks on
File
. They allow a file handle to acquire an exclusive or shared file lock, which blocks other file handles to the same file from acquiring a conflicting lock. Some semantics are platform dependent, and these are documented in the API documentation.Public API
Steps / History
Unresolved Questions
Footnotes
https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html ↩
The text was updated successfully, but these errors were encountered: