-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Introduce file:lock/2 and file:unlock/1 #6251
base: master
Are you sure you want to change the base?
Conversation
CT Test ResultsNo tests were run for this PR. This is either because the build failed, or the PR is based on a branch without GH actions tests configured. Results for commit 75645a3 To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass. See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally. Artifacts
// Erlang/OTP Github Action Bot |
Awesome @lukaszsamson! This would indeed be useful for Elixir! Some additional comments:
If the OTP team accepts this feature, there are also the following questions:
I would answer yes to all of the above but it is up to the OTP team, so I would wait for feedback before further changes. |
Co-authored-by: José Valim <[email protected]>
Co-authored-by: José Valim <[email protected]>
Co-authored-by: José Valim <[email protected]>
Co-authored-by: José Valim <[email protected]>
Hello! We will need to have an OTB (OTP Technical Board) meeting to talk about if and how we want to have this, but since it can be implemented on all supported platforms I don't see any reason why we would not want it.
I would also say yes to all of the above. |
Here's a build from a branch with updated preloaded (a check in kernel is failing as my machine differs from the one running GHA) https://github.com/lukaszsamson/otp/runs/8089001687?check_suite_focus=true |
Another thing to consider is if we would like to support only entire file locking (via BSD flock) or support range locking (via POSIX lockf or fcntl). I guess open file description locks via fcntl are out of the box as this is Linux only. Here's a nice summary of pros and cons of different Unix options (https://gavv.net/articles/file-locks/). Windows LockFileEx does support range locking. |
I believe |
Then maybe |
I started looking at this PR as we will soon have a meeting to discuss it. I'm putting some notes here in case you have any opinions. It would seem like Windows has decided to make the default I don't think we should support locking byte ranges. If we need that we can add it in another PR. It is too bad that there is no asynchronous API that we can use. Blocking a |
Windows API can be called asynchronously with IO completion ports. On unix fcntl has some async support but I couldn’t find anything about async locks |
Hello! We have (finally) made a decision and we would like this functionality. We propose that the API should be: -spec file:lock(file:io_device(), [shared | exclusive | non_blocking]) ->
ok | {error, already_locked | file:posix()}.
-spec file:unlock(file:io_device()) -> ok | {error, terminated}. I think that is the same as what has been discussed in this PR? |
Nice. We need to look into some details to make the API consistent
|
I did some testing on Windows.
Windows will fail with
On Windows you cannot upgrade a lock, but you can downgrade. That is you can do: FileLockEx(handle, EXCLUSIVE);
FileLockEx(handle, SHARED);
FileUnlockEx(handle, EXCLUSIVE); but you cannot do: FileLockEx(handle, SHARED);
FileLockEx(handle, EXCLUSIVE); // this will block or return ERROR_LOCK_VIOLATION
FileUnlockEx(handle, SHARED); Also, you can do as many shared locks are you like, but you need to do the same amount of unlocks for all the locks to be released. That is: FileLockEx(handle, SHARED);
FileLockEx(handle, SHARED);
FileLockEx(handle, SHARED);
FileLockEx(handle, SHARED);
FileUnlockEx(handle, SHARED);
FileLockEx(handle, EXCLUSIVE|NB); // ERROR_LOCK_VIOLATION
FileUnlockEx(handle, SHARED);
FileLockEx(handle, EXCLUSIVE|NB); // ERROR_LOCK_VIOLATION
FileUnlockEx(handle, SHARED);
FileLockEx(handle, EXCLUSIVE|NB); // ERROR_LOCK_VIOLATION
FileUnlockEx(handle, SHARED);
FileLockEx(handle, EXCLUSIVE|NB); // Success Here again, I think it would be good to keep a flag in the file structure so that any extra locks are just ignored so that we behave as on Unix.
You get |
Also locks on Windows are not only advisory, so if you do |
@garazdawi I applied your suggestions and split I'm not sure about
Do you think we should make it closer to POSIX, i.e. add support for nonatomic lock upgrade and make downgrade nonatomic? |
otherewise thread deadlocks
I made changes to Windows implementation to match unix. If a lock of a different type is already held then unlock is called before attempting to lock. |
We had another technical board meeting today to try to reconcile the differences between Unix and Windows, and have realized that the functionality differs too much between operating systems to pretend that it's the same function. There's no good way to compensate for this in Erlang. :-( We think it's time for us to refactor the file system support in Erlang by dividing it into several modules, one for generic and actually platform independent operations, and other modules for platform specific ones such as Windows, POSIX, BSD, Linux (which I suppose would cover those not in POSIX). This is something we've been thinking about for a long time but haven't had enough motivation for until now. We plan to get this done early in OTP 27 and we'll bring this PR in with it. |
Any updates @jhogberg @garazdawi? Is OTP27 still the target? |
This PR extends
file
module with new functionflock/2
. It allows locking files for shared or exclusive access on Unix and Windows.Rationale: Currently the OTP lacks suitable APIs allowing fine grained control over access to filesystem. Those can be especially useful for applications like language tools, compilers (e.g. elixir compiler), IDEs (like language servers) that share access to the same filesystem directories.
Please note that this is a first draft that received only a little testing on macOS platform. I would like to get some guidance if the direction I took is acceptable and if the OTP Team would be interested in merging this. The documentation will also need further improvements.
Related manpages and documentation:
CC @josevalim