Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public sealed override long Position
internal sealed override bool IsClosed => _fileHandle.IsClosed;

// Flushing is the responsibility of BufferedFileStreamStrategy
internal sealed override SafeFileHandle SafeFileHandle
internal override SafeFileHandle SafeFileHandle
{
get
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,32 @@ internal UnixFileStreamStrategy(string path, FileMode mode, FileAccess access, F
base(path, mode, access, share, options, preallocationSize, unixCreateMode)
{
}

internal override SafeFileHandle SafeFileHandle
{
get
{
if (CanSeek)
{
// The base SafeFileHandle getter synchronizes the file offset before exposing the handle
// since the in-memory position may be out-of-sync with the actual file position.
// However, some files such as certain pseudofiles on AzureLinux may report CanSeek = true
// but still fail with ESPIPE when attempting to seek. We tolerate this specific error
// to match the behavior in RandomAccess where we ignore pwrite and pread failures on certain file types.
long result = Interop.Sys.LSeek(_fileHandle, _filePosition, Interop.Sys.SeekWhence.SEEK_SET);
if (result < 0)
{
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
if (errorInfo.Error != Interop.Error.ESPIPE)
{
throw Interop.GetExceptionForIoErrno(errorInfo, _fileHandle.Path);
}
_fileHandle.SupportsRandomAccess = false;
}
}

return _fileHandle;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.DotNet.XUnitExtensions;
using Microsoft.Win32.SafeHandles;
using System;
using System.IO;
Expand Down Expand Up @@ -64,5 +65,25 @@ public void AccessFlushesFileClosesHandle()
Assert.Equal(TestBuffer.Length, fsr.Length);
}
}

[ConditionalFact]
[PlatformSpecific(TestPlatforms.Linux)]
public void SafeFileHandle_PseudoFile_DoesNotThrow()
{
// On some Linux distributions (e.g., AzureLinux 3), pseudofiles may report CanSeek = true
// but fail when attempting to seek. Accessing SafeFileHandle should not throw in these cases.
string path = File.Exists("/proc/net/route")
? "/proc/net/route"
: File.Exists("/proc/version")
? "/proc/version"
: throw new SkipTestException("Can't find a pseudofile to test.");

using FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// This should not throw even if the file reports CanSeek = true but doesn't support seeking
SafeFileHandle handle = fs.SafeFileHandle;

Assert.NotNull(handle);
Assert.False(handle.IsClosed);
}
}
}
Loading