Skip to content
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

Tracking Issue for File lock API #130994

Open
2 of 3 tasks
cberner opened this issue Sep 28, 2024 · 19 comments · May be fixed by #136794
Open
2 of 3 tasks

Tracking Issue for File lock API #130994

cberner opened this issue Sep 28, 2024 · 19 comments · May be fixed by #136794
Labels
C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. I-libs-api-nominated Nominated for discussion during a libs-api team meeting. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. to-announce Announce this issue on triage meeting

Comments

@cberner
Copy link
Contributor

cberner commented Sep 28, 2024

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

impl File {
    fn lock(&self) -> io::Result<()>;
    fn lock_shared(&self) -> io::Result<()>;
    fn try_lock(&self) -> io::Result<bool>;
    fn try_lock_shared(&self) -> io::Result<bool>;
    fn unlock(&self) -> io::Result<()>;
}

Steps / History

Unresolved Questions

  • None yet.

Footnotes

  1. https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html

@cberner cberner added C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Sep 28, 2024
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Nov 11, 2024
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
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Nov 11, 2024
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
mati865 pushed a commit to mati865/rust that referenced this issue Nov 12, 2024
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
@workingjubilee
Copy link
Member

apparently not supported on all tier 2 OS: #132921

@eric-seppanen
Copy link

eric-seppanen commented Nov 27, 2024

Note that this triggers the unstable_name_collisions lint for code using the fs2/fs3/fs4 crates, all of which have a FileExt trait with methods called lock_shared, try_lock_shared, and unlock.

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.

@NilsIrl
Copy link

NilsIrl commented Dec 20, 2024

It would also be useful to atomically create and lock a file. This is possible on MacOS using the O_SHLOCK and O_EXLOCK flags on open and on Linux using O_TMPFILE.

@joshtriplett
Copy link
Member

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

@rfcbot
Copy link

rfcbot commented Jan 26, 2025

Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

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.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Jan 26, 2025
@m-ou-se
Copy link
Member

m-ou-se commented Jan 30, 2025

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".

@m-ou-se
Copy link
Member

m-ou-se commented Jan 30, 2025

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.

@m-ou-se
Copy link
Member

m-ou-se commented Jan 30, 2025

I'm checking my box with the assumption that these are just small docs changes that we'll do during/before stabilization.

@rfcbot rfcbot added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels Jan 30, 2025
@rfcbot
Copy link

rfcbot commented Jan 30, 2025

🔔 This is now entering its final comment period, as per the review above. 🔔

@joshtriplett
Copy link
Member

I've submitted #136288 which should address all the documentation requests.

@m-ou-se wrote:

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.

Done.

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".

"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 try_ methods return Ok(false)). I've also clarified the return value documentation to avoid that ambiguity.

The unlock method should document whether it's okay to call it if no locks are held.

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.

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.

It's always OK (unlike a mutex or similar). It'll never explode.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Jan 30, 2025
…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 .)
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Jan 31, 2025
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 .)
github-actions bot pushed a commit to rust-lang/miri that referenced this issue Jan 31, 2025
…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 .)
@rfcbot rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. to-announce Announce this issue on triage meeting and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels Feb 9, 2025
@rfcbot
Copy link

rfcbot commented Feb 9, 2025

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.

@cberner cberner linked a pull request Feb 9, 2025 that will close this issue
@quininer
Copy link
Contributor

I think this API needs more warnings for Windows, as LockFile might not be the right choice.
It has many inconsistencies with unix file lock, and using it blindly would be a mistake. like #54118 (comment) and LockFileEx Remarks .

Finally, i used share mode instead of file lock, which is similar to the open options api mentioned by #130994 (comment).

@m-ou-se m-ou-se added the I-libs-api-nominated Nominated for discussion during a libs-api team meeting. label Feb 11, 2025
@joshtriplett
Copy link
Member

joshtriplett commented Feb 11, 2025

@quininer I don't think share mode is close enough to things available on other platforms that we'd be able to build a common portable API around it, and it doesn't allow keeping a file open and only occasionally locking it. I'd be all for adding a "share mode" option to Windows' OpenOptionsExt, but that'd be a separate feature which we already have.

The issue with append-only files would be worth some documentation on the append method and the locking methods. I don't think that's a blocker. On some platforms, locking won't work at all.

The rest of the "remarks" section on LockFileEx doesn't seem to have any caveats that we should consider a blocker.

@quininer
Copy link
Contributor

@joshtriplett We already have share_mode for Windows, which is good. :D

If the locking process opens the file a second time, it cannot access the specified region through this second handle until it unlocks the region.
Locking a portion of a file for exclusive access denies all other processes both read and write access to the specified region of the file.

This means that the windows file lock is different from unix file lock in that it is not a advisory lock and it blocks file access. This is rather different from what std document implies

Note, this is an advisory lock meant to interact with lock_shared, try_lock, try_lock_shared, and unlock.

I actually think the windows file lock is different enough from unix file lock that it should be in FileExt as well. Even if it isn't, there should be a more document warning.

@cberner
Copy link
Contributor Author

cberner commented Feb 11, 2025

@quininer the std documentation currently says Its interactions with other methods, such as [read] and [write] are platform specific, and it may or may not cause non-lockholders to block.

That's meant to say that the lock may be mandatory, depending on the platform (i.e. Windows). How would you make it more clear?

@quininer
Copy link
Contributor

@cberner Ha, that's good enough. but I didn't realize it at first. :(

@joshtriplett
Copy link
Member

I've clarified the documentation in #136876 to address all of these issues.

@ChrisDenton
Copy link
Member

LockFileEx won't work with append only files. You'd need either need to add read or else use write and not append.

@joshtriplett
Copy link
Member

@ChrisDenton That's exactly what I've written in #136876.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. I-libs-api-nominated Nominated for discussion during a libs-api team meeting. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. to-announce Announce this issue on triage meeting
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants