-
Couldn't load subscription status.
- Fork 5.2k
Fix ESPIPE error when accessing SafeFileHandle on pseudofiles #120751
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
Conversation
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
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.
Pull Request Overview
This PR fixes an issue where accessing FileStream.SafeFileHandle throws an IOException on certain pseudofiles (like /proc/net/route) on AzureLinux 3 that incorrectly report CanSeek = true but fail with ESPIPE when seeking is attempted.
Key Changes:
- Modified
SafeFileHandleproperty inOSFileStreamStrategyto allow platform-specific overrides - Added Unix-specific override in
UnixFileStreamStrategythat toleratesESPIPEerrors during position synchronization - Enhanced
FileStreamHelpers.Seekon Unix to optionally ignore seek errors
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| OSFileStreamStrategy.cs | Removed sealed modifier from SafeFileHandle property to enable platform-specific overrides |
| UnixFileStreamStrategy.cs | Overrode SafeFileHandle getter to pass ignoreSeekErrors: true when syncing position |
| FileStreamHelpers.Unix.cs | Added optional ignoreSeekErrors parameter to Seek method to silently handle ESPIPE errors |
| SafeFileHandle.cs | Added unit tests to verify SafeFileHandle access works on pseudofiles without throwing |
src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/FileStream/SafeFileHandle.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/FileStream/SafeFileHandle.cs
Outdated
Show resolved
Hide resolved
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.
@copilot please see my comments
src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
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.
We are almost there, @copliot please just apply my suggestion.
src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs
Outdated
Show resolved
Hide resolved
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.
LGTM, thanks!
src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs
Show resolved
Hide resolved
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.
Let's improve it based on provided feedback.
/proc/net/routereports CanSeek=true but lseek() fails with ESPIPE on AzureLinux 3Changes Made
Original prompt
This section details on the original issue you should resolve
<issue_title>Cannot seek on pseudofiles on AzureLinux but CanSeek = true</issue_title>
<issue_description>Related to #120577.
The assert at
runtime/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
Line 340 in cbf483b
trips on AzureLinux 3 when opening pseudofiles such as
/proc/net/route. The assert has been relaxed by #120736 to unblock CI (as the tests don't fail on Release builds since they don't actually seek in the file), but following piece of code still throws on AzureLinux3I don't have access to an AzureLinux VM to do more experiments (this does not reproduce via docker), but we should also check if Seek() followed by Read actually reads data at given offset from the pseudofile.</issue_description>
<agent_instructions>Follow my instructions listed in #120741 (comment), add a unit test based on sample provided by the original poster.</agent_instructions>
Comments on the Issue (you are @copilot in this section)
@rzikm cc @adamsitnik @vcsjones This reproduces for me in a stock AZL3 VM:You can download ISOs at https://aka.ms/azurelinux-3.0-x86_64.iso for x64 or https://aka.ms/azurelinux-3.0-aarch64.iso for ARM64. They work fine in Hyper-V or Parallels if you want to play with Azure Linux locally.
That makes sense; the seek behavior is probably driven by the kernel, not any particular user-land component.</comment_new>
<comment_new>@adamsitnik
Historical context: before the FileStream rewrite in .NET 6, we were using sys-calls that were always updating the file handle position in all cases except of async IO on Windows, where for every async read or write, we were updating the position by calling another sys-call (on Windows
writefileandreadfilecan't update the handle position for async IO). To simplify all of that, we decided to always use sys-calls that require the offset to be provided in explicit way and store the offset in memory. Thanks to that allSeekandPositioncalls are now simple field access operations rather than expensive sys-calls. (more)But for the sake of backward compatibility, for those who use the raw handle exposed by the
FileStream, we decided to sync the handle position when the handle is requested. So those who use the sys-calls that update the handle position don't run into silent bugs by reading/writing fromoffset = 0(despiteFileStream.Positionhaving different value) shown by the following pseudocode:Triage: similarly to what we do for
RandomAccesshere:runtime/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs
Lines 39 to 46 in 13566e1
We should just ignore the specific error when
Seekfails when called from here:runtime/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs
Lines 96 to 105 in 13566e1
The fix should just overwrite the
SafeFileHandlegetter for UnixFileStreamStrategy.cs and keep it as is for Windows.Fixes #120741
💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.