dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.26k stars 4.73k forks source link

IOException in FileStreamHelpers.CheckFileCall on Linux when reading from file #78016

Open patrickmurray18 opened 1 year ago

patrickmurray18 commented 1 year ago

Description

I am publishing a dotnet6 app from Windows and exporting to Linux (runtime=ubuntu.16.04-x64). At one point when my app tries to read from a device character file it fails (see below for exception).

No other errors are encountered in the course of opening the file, querying the file etc. This appears to be due to the use of BinaryReader, just using FileStream doesn't fail like this.

Reproduction Steps

Publishing this and running on Linux (mine is xfce) is sufficient to cause the exception.

using (FileStream fs = new
       (
           "/dev/input/event2",
           FileMode.Open,
           FileAccess.Read,
           FileShare.ReadWrite
       ))
{
    using (BinaryReader br = new(fs))
    {
        br.ReadInt32();
    }
}

Expected behavior

It should work as if calling FileStream.Read on the underlying file stream or at least give a more informative error if BinaryReader explicitly doesn't support special files.

Actual behavior

Exception is thrown when the reproduction code is run:

ExceptionType: IOException Message: Invalid argument : '/dev/input/event2' Source: System.Private.CoreLib StackTrace: at System.IO.Strategies.FileStreamHelpers.CheckFileCall(Int64 result, String path, Boolean ignoreNotSupported) at System.IO.RandomAccess.ReadAtOffset(SafeFileHandle handle, Span`1 buffer, Int64 fileOffset) at System.IO.Strategies.OSFileStreamStrategy.Read(Span`1 buffer) at System.IO.Strategies.OSFileStreamStrategy.Read(Byte[] buffer, Int32 offset, Int32 count) at System.IO.Strategies.BufferedFileStreamStrategy.ReadSpan(Span`1 destination, ArraySegment`1 arraySegment) at System.IO.Strategies.BufferedFileStreamStrategy.Read(Byte[] buffer, Int32 offset, Int32 count) at System.IO.FileStream.Read(Byte[] buffer, Int32 offset, Int32 count) at System.IO.BinaryReader.InternalRead(Int32 numBytes) at System.IO.BinaryReader.ReadUInt32()

Regression?

No response

Known Workarounds

Just using FileStream appears to be a workaround.

Configuration

Publish command looks like this: dotnet publish /p:Configuration="Debug" /p:Platform="Any CPU" -r "ubuntu.16.04-x64" --self-contained

Development machine:

dotnet --info .NET SDK (reflecting any global.json): Version: 6.0.305 Commit: de9a4b2f4b

Runtime Environment: OS Name: Windows OS Version: 10.0.19044 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\6.0.305\

global.json file: Not found

Host: Version: 6.0.10 Architecture: x64 Commit: 5a400c212a

.NET SDKs installed: 2.1.524 [C:\Program Files\dotnet\sdk] 3.1.424 [C:\Program Files\dotnet\sdk] 6.0.301 [C:\Program Files\dotnet\sdk] 6.0.305 [C:\Program Files\dotnet\sdk]

.NET runtimes installed: Microsoft.AspNetCore.All 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.30 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Download .NET: https://aka.ms/dotnet-download

Learn about .NET Runtimes and SDKs: https://aka.ms/dotnet/runtimes-sdk-info

Other information

No response

ghost commented 1 year ago

Tagging subscribers to this area: @dotnet/area-system-io See info in area-owners.md if you want to be subscribed.

Issue Details
### Description I am publishing a dotnet6 app from Windows and exporting to Linux (runtime=`ubuntu.16.04-x64`). At one point when my app tries to read from a device character file it fails (see below for exception). No other errors are encountered in the course of opening the file, querying the file etc. This appears to be due to the use of `BinaryReader`, just using `FileStream` doesn't fail like this. ### Reproduction Steps Publishing this and running on Linux (mine is xfce) is sufficient to cause the exception. ``` using (FileStream fs = new ( "/dev/input/event2", FileMode.Open, FileAccess.Read, FileShare.ReadWrite )) { using (BinaryReader br = new(fs)) { br.ReadInt32(); } }``` ### Expected behavior It should work as if calling `FileStream.Read` on the underlying file stream or at least give a more informative error if `BinaryReader` explicitly doesn't support special files. ### Actual behavior Exception is thrown when the reproduction code is run: > ExceptionType: IOException > Message: Invalid argument : '/dev/input/event2' > Source: System.Private.CoreLib > StackTrace: at System.IO.Strategies.FileStreamHelpers.CheckFileCall(Int64 result, String path, Boolean ignoreNotSupported) > at System.IO.RandomAccess.ReadAtOffset(SafeFileHandle handle, Span\`1 buffer, Int64 fileOffset) > at System.IO.Strategies.OSFileStreamStrategy.Read(Span\`1 buffer) > at System.IO.Strategies.OSFileStreamStrategy.Read(Byte[] buffer, Int32 offset, Int32 count) > at System.IO.Strategies.BufferedFileStreamStrategy.ReadSpan(Span\`1 destination, ArraySegment\`1 arraySegment) > at System.IO.Strategies.BufferedFileStreamStrategy.Read(Byte[] buffer, Int32 offset, Int32 count) > at System.IO.FileStream.Read(Byte[] buffer, Int32 offset, Int32 count) > at System.IO.BinaryReader.InternalRead(Int32 numBytes) > at System.IO.BinaryReader.ReadUInt32() ### Regression? _No response_ ### Known Workarounds Just using `FileStream` appears to be a workaround. ### Configuration Publish command looks like this: dotnet publish /p:Configuration="Debug" /p:Platform="Any CPU" -r "ubuntu.16.04-x64" --self-contained Development machine: >dotnet --info .NET SDK (reflecting any global.json): Version: 6.0.305 Commit: de9a4b2f4b Runtime Environment: OS Name: Windows OS Version: 10.0.19044 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\6.0.305\ global.json file: Not found Host: Version: 6.0.10 Architecture: x64 Commit: 5a400c212a .NET SDKs installed: 2.1.524 [C:\Program Files\dotnet\sdk] 3.1.424 [C:\Program Files\dotnet\sdk] 6.0.301 [C:\Program Files\dotnet\sdk] 6.0.305 [C:\Program Files\dotnet\sdk] .NET runtimes installed: Microsoft.AspNetCore.All 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.30 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Download .NET: https://aka.ms/dotnet-download Learn about .NET Runtimes and SDKs: https://aka.ms/dotnet/runtimes-sdk-info ### Other information _No response_
Author: patrickmurray18
Assignees: -
Labels: `area-System.IO`
Milestone: -
patrickmurray18 commented 1 year ago

Correction to the above: FileStream.Read actually fails in the same way. FileStream.ReadByte works however.

adamsitnik commented 1 year ago

It seems to be https://github.com/dotnet/runtime/issues/59754 which I thought we have fixed in https://github.com/dotnet/runtime/pull/59846.

@Jozkee could you PTAL? It looks like we are missing some error handling in

https://github.com/dotnet/runtime/blob/8918adf2e5255920aed3c61f9b92c2a51eec0fe3/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs#L39-L48

adamsitnik commented 1 year ago

@Jozkee ping