-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
FileStream.Unix: improve DeleteOnClose when FileShare.None. #55327
Conversation
Use FileShare.None lock to detect when another Handle that has DeleteOnClose deleted the file, and then re-open it.
Tagging subscribers to this area: @dotnet/area-system-io Issue DetailsUse FileShare.None lock to detect when another Handle that has @adamsitnik @stephentoub ptal.
|
On Linux, NuGet doesn't clean up its lock files because I was looking introducing some specific cleanup logic in NuGet/NuGet.Client#4123. cc @zivkan |
What are the issues? EDIT: nevermind, I see your description in the nuget pr. |
FWIW, I think it makes a lot of sense to fix it in the runtime. The intent of:
is very clear and there is no doubt what it wants to achieve. So it is quite dangerous that currently this works on Windows but it is broken on Linux. |
The test I've added is failing. I need to take a closer look. |
FWIW, the nuget.org server team coincidentally contacted me asking if it's possible for client to make duplicate HTTP requests to the same URL. This got me thinking about this PR. Is it possible that two processes/threads opening a file with edit: 90%+ of instances are on Linux, but it's also happening on Windows. NuGet guards simultaneous downloads of the same package via a lock file, hence why I thought of this PR. |
CI failures seem unrelated now.
No. One will fail the lock and throw: runtime/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs Lines 285 to 293 in 145e588
|
@adamsitnik This PR is assigned to you for follow-up/decision before the RC1 snap. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of calling unlink before unlocking the file. We could also let close()
unlock it for us and call flock(LOCK_UN)
only when close()
fails.
But with the proposed solution I am not sure if we are able to guarantee that FileShare.None
combined with DeleteOnClose
can be used as a safe global lock.
In case of NuGet, they should rather use FileMode.CreateNew
instead of FileMode.OpenOrCreate
it's mapped to O_EXCL
:
runtime/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
Lines 232 to 233 in 7249ec4
case FileMode.CreateNew: | |
flags |= (Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_EXCL); |
From https://man7.org/linux/man-pages/man2/open.2.html:
Ensure that this call creates the file: if this flag is
specified in conjunction with O_CREAT, and pathname
already exists, then open() fails with the error EEXIST.
Which combined with DeleteOnClose
should serve as pretty good global lock. Please correct me if I am wrong.
src/libraries/System.IO.FileSystem/tests/FileStream/DeleteOnClose.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
Show resolved
Hide resolved
src/libraries/System.IO.FileSystem/tests/FileStream/DeleteOnClose.cs
Outdated
Show resolved
Hide resolved
The trouble is when the file already exists. There is no way to open it and be sure you and the other process are referring to the same file entry. The change does this by performing |
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
Outdated
Show resolved
Hide resolved
…n it doesn't exist.
@adamsitnik can you take another look? |
ping @adamsitnik |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the patience, @tmds . I left a few comments.
src/libraries/System.IO.FileSystem/tests/FileStream/DeleteOnClose.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Carlos Sanchez <[email protected]>
Use FileShare.None lock to detect when another Handle that has
DeleteOnClose deleted the file, and then re-open it.
@adamsitnik @stephentoub ptal.