Skip to content

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes - #132077

Merged
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound
Aug 11, 2026
Merged

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes#132077
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound

Conversation

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

fixes#131503

CopilotAIand others added 2 commits August 10, 2026 12:51
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 adjusts how SafeFileHandle.CanSeek is determined and cached so FileStream construction works reliably on Windows for handles that can’t be safely probed via file-type detection (notably write-only named pipes), and adds a regression test to cover the scenario.

Changes:

  • Centralizes SafeFileHandle.CanSeek caching state in the shared SafeFileHandle partial.
  • Updates Windows seekability probing to use SetFilePointerEx(..., 0, FILE_CURRENT) and cache the result.
  • Adds a Windows test validating FileStream construction over a write-only named-pipe handle (sync and overlapped) reports CanSeek == false and preserves IsAsync.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.csAdds a regression theory for FileStream over write-only named-pipe handles (sync/overlapped).
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.csImplements Windows seekability probing via SetFilePointerEx and caches the result.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.csRemoves the per-Unix CanSeek member/field now that caching is centralized.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.csAdds shared _canSeek cache and CanSeek property used by platform-specific implementations.
Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:98

  • After switching to Interop.Kernel32.CreateNamedPipeFileHandle, the local CreateNamedPipe P/Invoke is redundant and should be removed to avoid carrying duplicate interop declarations.
 [DllImport("kernel32.dll", EntryPoint = "CreateNamedPipeW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateNamedPipe(
string pipeName,
int openMode,
int pipeMode,

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:03

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

Addressed the requested review feedback in 17a1774.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:76

  • SECURITY_ATTRIBUTES is passed by ref with nLength == 0 and the pipe name omits the LOCAL namespace. Initializing SECURITY_ATTRIBUTES via the helper and using the \\.\pipe\LOCAL\... naming pattern (as used by SafeFileHandle.CreateAnonymousPipe) makes this test more robust on AppContainer scenarios and avoids relying on an uninitialized SECURITY_ATTRIBUTES layout.
 Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default;
using SafeFileHandle handle = Interop.Kernel32.CreateNamedPipeFileHandle(
$@"\\.\pipe\{Guid.NewGuid():N}",

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback and fix the test project build

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:54

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback and fix the test project build

Addressed in 6cbbf8f. The test now uses only PIPE_ACCESS_OUTBOUND, and the Windows test project includes the required shared named-pipe interop sources.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@adamsitnik
adamsitnik marked this pull request as ready for review August 10, 2026 15:11
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:75

  • The test creates the named pipe using the plain \\.\pipe\... namespace. In AppContainer environments Windows requires the \\.\pipe\LOCAL\ prefix (see SafeFileHandle.Windows.cs where CreateAnonymousPipe uses \\.\pipe\LOCAL\... for this reason), so this test can fail under those runs.

Consider using the LOCAL namespace unconditionally (it works both inside and outside AppContainer) to keep the test robust across CI environments.

 $@"\\.\pipe\{Guid.NewGuid():N}",

CopilotAI review requested due to automatic review settings August 10, 2026 17:22
@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs:342

  • GetCanSeekCore currently treats any FILE_TYPE_DISK handle as seekable when _cachedFileType is unset, which is broader than the previous Type == RegularFile behavior and can permanently cache an incorrect true result (e.g., for directory/symlink handles) without ever consulting the more specific file-type logic. It also doesn’t match the PR description’s claim of probing seekability with SetFilePointerEx. Consider keeping the cheap pipe-safe GetFileType gate, but use the existing SetFilePointerEx probe for disk handles (and fast-path known-regular files opened via SafeFileHandle.Open).
 // That is why we use the cached file type (if available), and if not available, we use GetFileType to determine whether the file is seekable or not.
private bool GetCanSeekCore() => _cachedFileType != -1
? (FileHandleType)_cachedFileType == FileHandleType.RegularFile
: Interop.Kernel32.GetFileType(this) == Interop.Kernel32.FileTypes.FILE_TYPE_DISK;

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the benchmark results show there is no performance regression (actually, even a small improvement):

BenchmarkDotNet v0.16.0-preview.1, Windows 11 (10.0.26100.33158/24H2/2024Update/HudsonValley) (Hyper-V)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 8 logical and 4 physical cores
Memory: 31.99 GB Total, 27.1 GB Available
.NET SDK 11.0.100-rc.1.26410.104
[Host] : .NET 11.0.0 (11.0.0-rc.1.26410.104, 11.0.26.41104), X64 RyuJIT x86-64-v4
MethodToolchainMeanErrorRatioAllocatedAlloc Ratio
ReadAllBytesmain25.05 μs0.483 μs1.021104 B1.00
ReadAllBytesPR #13207724.62 μs0.467 μs1.001104 B1.00
ReadAllBytesAsyncmain48.17 μs0.702 μs1.061624 B1.00
ReadAllBytesAsyncPR #13207745.58 μs0.901 μs1.001624 B1.00
OpenAndCanSeekmain11.23 μs0.112 μs1.01248 B1.00
OpenAndCanSeekPR #13207711.13 μs0.103 μs1.00248 B1.00

Full logs

@adamsitnikadamsitnik changed the title Fix FileStream initialization for write-only named pipesEnsure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipesAug 11, 2026
@adamsitnikadamsitnik added this to the 11.0.0 milestone Aug 11, 2026
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g networking test failures are unrelated

@adamsitnik
adamsitnik merged commit c82af78 into mainAug 11, 2026
130 of 132 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-regression-test-pipe-access-outbound branch August 11, 2026 16:25
@dotnet-milestone-botdotnet-milestone-botBot modified the milestones: 11.0.0, 11.0-rc1Aug 12, 2026
jozkee added a commit that referenced this pull request Aug 12, 2026
Follow-up to #132077.
## Summary
- Determine Windows `SafeFileHandle.CanSeek` directly from the raw
`GetFileType` result instead of the cached, refined
`SafeFileHandle.Type` value.
- Add symbolic-link regression tests covering `Type` access both before
and after `FileStream` evaluates `CanSeek`.
## Rationale
For handles opened on a symbolic link, Windows reports `FILE_TYPE_DISK`,
while `SafeFileHandle.Type` refines that to `SymbolicLink`. As a result,
#132077 could cache different `CanSeek` values depending on whether
`Type` was queried before constructing the `FileStream`. Using the raw
file type restores access-order-independent behavior while retaining the
write-only named-pipe fix.
## Validation
- `.\build.cmd clr.corelib` — succeeded with 0 warnings and 0 errors.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedByType` — passed.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedBySubsequentTypeAccess`
— passed.
- `FileStream_WriteOnlyNamedPipe_CanSeek_IsAsync` — 2 cases passed.
No baseline build was run.
> [!NOTE]
> This pull request description was generated with GitHub Copilot.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FileStream over write-only overlapped named pipe handle throws UnauthorizedAccessException on .NET 11 (regression from .NET 10)

4 participants

@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes by Copilot · Pull Request #132077 · dotnet/runtime · GitHub
Skip to content

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes - #132077

Merged
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound
Aug 11, 2026
Merged

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes#132077
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound

Conversation

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

fixes#131503

CopilotAIand others added 2 commits August 10, 2026 12:51
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 adjusts how SafeFileHandle.CanSeek is determined and cached so FileStream construction works reliably on Windows for handles that can’t be safely probed via file-type detection (notably write-only named pipes), and adds a regression test to cover the scenario.

Changes:

  • Centralizes SafeFileHandle.CanSeek caching state in the shared SafeFileHandle partial.
  • Updates Windows seekability probing to use SetFilePointerEx(..., 0, FILE_CURRENT) and cache the result.
  • Adds a Windows test validating FileStream construction over a write-only named-pipe handle (sync and overlapped) reports CanSeek == false and preserves IsAsync.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.csAdds a regression theory for FileStream over write-only named-pipe handles (sync/overlapped).
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.csImplements Windows seekability probing via SetFilePointerEx and caches the result.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.csRemoves the per-Unix CanSeek member/field now that caching is centralized.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.csAdds shared _canSeek cache and CanSeek property used by platform-specific implementations.
Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:98

  • After switching to Interop.Kernel32.CreateNamedPipeFileHandle, the local CreateNamedPipe P/Invoke is redundant and should be removed to avoid carrying duplicate interop declarations.
 [DllImport("kernel32.dll", EntryPoint = "CreateNamedPipeW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateNamedPipe(
string pipeName,
int openMode,
int pipeMode,

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:03

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

Addressed the requested review feedback in 17a1774.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:76

  • SECURITY_ATTRIBUTES is passed by ref with nLength == 0 and the pipe name omits the LOCAL namespace. Initializing SECURITY_ATTRIBUTES via the helper and using the \\.\pipe\LOCAL\... naming pattern (as used by SafeFileHandle.CreateAnonymousPipe) makes this test more robust on AppContainer scenarios and avoids relying on an uninitialized SECURITY_ATTRIBUTES layout.
 Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default;
using SafeFileHandle handle = Interop.Kernel32.CreateNamedPipeFileHandle(
$@"\\.\pipe\{Guid.NewGuid():N}",

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback and fix the test project build

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:54

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback and fix the test project build

Addressed in 6cbbf8f. The test now uses only PIPE_ACCESS_OUTBOUND, and the Windows test project includes the required shared named-pipe interop sources.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@adamsitnik
adamsitnik marked this pull request as ready for review August 10, 2026 15:11
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:75

  • The test creates the named pipe using the plain \\.\pipe\... namespace. In AppContainer environments Windows requires the \\.\pipe\LOCAL\ prefix (see SafeFileHandle.Windows.cs where CreateAnonymousPipe uses \\.\pipe\LOCAL\... for this reason), so this test can fail under those runs.

Consider using the LOCAL namespace unconditionally (it works both inside and outside AppContainer) to keep the test robust across CI environments.

 $@"\\.\pipe\{Guid.NewGuid():N}",

CopilotAI review requested due to automatic review settings August 10, 2026 17:22
@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs:342

  • GetCanSeekCore currently treats any FILE_TYPE_DISK handle as seekable when _cachedFileType is unset, which is broader than the previous Type == RegularFile behavior and can permanently cache an incorrect true result (e.g., for directory/symlink handles) without ever consulting the more specific file-type logic. It also doesn’t match the PR description’s claim of probing seekability with SetFilePointerEx. Consider keeping the cheap pipe-safe GetFileType gate, but use the existing SetFilePointerEx probe for disk handles (and fast-path known-regular files opened via SafeFileHandle.Open).
 // That is why we use the cached file type (if available), and if not available, we use GetFileType to determine whether the file is seekable or not.
private bool GetCanSeekCore() => _cachedFileType != -1
? (FileHandleType)_cachedFileType == FileHandleType.RegularFile
: Interop.Kernel32.GetFileType(this) == Interop.Kernel32.FileTypes.FILE_TYPE_DISK;

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the benchmark results show there is no performance regression (actually, even a small improvement):

BenchmarkDotNet v0.16.0-preview.1, Windows 11 (10.0.26100.33158/24H2/2024Update/HudsonValley) (Hyper-V)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 8 logical and 4 physical cores
Memory: 31.99 GB Total, 27.1 GB Available
.NET SDK 11.0.100-rc.1.26410.104
[Host] : .NET 11.0.0 (11.0.0-rc.1.26410.104, 11.0.26.41104), X64 RyuJIT x86-64-v4
MethodToolchainMeanErrorRatioAllocatedAlloc Ratio
ReadAllBytesmain25.05 μs0.483 μs1.021104 B1.00
ReadAllBytesPR #13207724.62 μs0.467 μs1.001104 B1.00
ReadAllBytesAsyncmain48.17 μs0.702 μs1.061624 B1.00
ReadAllBytesAsyncPR #13207745.58 μs0.901 μs1.001624 B1.00
OpenAndCanSeekmain11.23 μs0.112 μs1.01248 B1.00
OpenAndCanSeekPR #13207711.13 μs0.103 μs1.00248 B1.00

Full logs

@adamsitnikadamsitnik changed the title Fix FileStream initialization for write-only named pipesEnsure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipesAug 11, 2026
@adamsitnikadamsitnik added this to the 11.0.0 milestone Aug 11, 2026
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g networking test failures are unrelated

@adamsitnik
adamsitnik merged commit c82af78 into mainAug 11, 2026
130 of 132 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-regression-test-pipe-access-outbound branch August 11, 2026 16:25
@dotnet-milestone-botdotnet-milestone-botBot modified the milestones: 11.0.0, 11.0-rc1Aug 12, 2026
jozkee added a commit that referenced this pull request Aug 12, 2026
Follow-up to #132077.
## Summary
- Determine Windows `SafeFileHandle.CanSeek` directly from the raw
`GetFileType` result instead of the cached, refined
`SafeFileHandle.Type` value.
- Add symbolic-link regression tests covering `Type` access both before
and after `FileStream` evaluates `CanSeek`.
## Rationale
For handles opened on a symbolic link, Windows reports `FILE_TYPE_DISK`,
while `SafeFileHandle.Type` refines that to `SymbolicLink`. As a result,
#132077 could cache different `CanSeek` values depending on whether
`Type` was queried before constructing the `FileStream`. Using the raw
file type restores access-order-independent behavior while retaining the
write-only named-pipe fix.
## Validation
- `.\build.cmd clr.corelib` — succeeded with 0 warnings and 0 errors.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedByType` — passed.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedBySubsequentTypeAccess`
— passed.
- `FileStream_WriteOnlyNamedPipe_CanSeek_IsAsync` — 2 cases passed.
No baseline build was run.
> [!NOTE]
> This pull request description was generated with GitHub Copilot.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FileStream over write-only overlapped named pipe handle throws UnauthorizedAccessException on .NET 11 (regression from .NET 10)

4 participants

@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes by Copilot · Pull Request #132077 · dotnet/runtime · GitHub
Skip to content

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes - #132077

Merged
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound
Aug 11, 2026
Merged

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes#132077
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound

Conversation

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

fixes#131503

CopilotAIand others added 2 commits August 10, 2026 12:51
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 adjusts how SafeFileHandle.CanSeek is determined and cached so FileStream construction works reliably on Windows for handles that can’t be safely probed via file-type detection (notably write-only named pipes), and adds a regression test to cover the scenario.

Changes:

  • Centralizes SafeFileHandle.CanSeek caching state in the shared SafeFileHandle partial.
  • Updates Windows seekability probing to use SetFilePointerEx(..., 0, FILE_CURRENT) and cache the result.
  • Adds a Windows test validating FileStream construction over a write-only named-pipe handle (sync and overlapped) reports CanSeek == false and preserves IsAsync.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.csAdds a regression theory for FileStream over write-only named-pipe handles (sync/overlapped).
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.csImplements Windows seekability probing via SetFilePointerEx and caches the result.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.csRemoves the per-Unix CanSeek member/field now that caching is centralized.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.csAdds shared _canSeek cache and CanSeek property used by platform-specific implementations.
Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:98

  • After switching to Interop.Kernel32.CreateNamedPipeFileHandle, the local CreateNamedPipe P/Invoke is redundant and should be removed to avoid carrying duplicate interop declarations.
 [DllImport("kernel32.dll", EntryPoint = "CreateNamedPipeW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateNamedPipe(
string pipeName,
int openMode,
int pipeMode,

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:03

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

Addressed the requested review feedback in 17a1774.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:76

  • SECURITY_ATTRIBUTES is passed by ref with nLength == 0 and the pipe name omits the LOCAL namespace. Initializing SECURITY_ATTRIBUTES via the helper and using the \\.\pipe\LOCAL\... naming pattern (as used by SafeFileHandle.CreateAnonymousPipe) makes this test more robust on AppContainer scenarios and avoids relying on an uninitialized SECURITY_ATTRIBUTES layout.
 Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default;
using SafeFileHandle handle = Interop.Kernel32.CreateNamedPipeFileHandle(
$@"\\.\pipe\{Guid.NewGuid():N}",

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback and fix the test project build

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:54

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback and fix the test project build

Addressed in 6cbbf8f. The test now uses only PIPE_ACCESS_OUTBOUND, and the Windows test project includes the required shared named-pipe interop sources.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@adamsitnik
adamsitnik marked this pull request as ready for review August 10, 2026 15:11
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:75

  • The test creates the named pipe using the plain \\.\pipe\... namespace. In AppContainer environments Windows requires the \\.\pipe\LOCAL\ prefix (see SafeFileHandle.Windows.cs where CreateAnonymousPipe uses \\.\pipe\LOCAL\... for this reason), so this test can fail under those runs.

Consider using the LOCAL namespace unconditionally (it works both inside and outside AppContainer) to keep the test robust across CI environments.

 $@"\\.\pipe\{Guid.NewGuid():N}",

CopilotAI review requested due to automatic review settings August 10, 2026 17:22
@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs:342

  • GetCanSeekCore currently treats any FILE_TYPE_DISK handle as seekable when _cachedFileType is unset, which is broader than the previous Type == RegularFile behavior and can permanently cache an incorrect true result (e.g., for directory/symlink handles) without ever consulting the more specific file-type logic. It also doesn’t match the PR description’s claim of probing seekability with SetFilePointerEx. Consider keeping the cheap pipe-safe GetFileType gate, but use the existing SetFilePointerEx probe for disk handles (and fast-path known-regular files opened via SafeFileHandle.Open).
 // That is why we use the cached file type (if available), and if not available, we use GetFileType to determine whether the file is seekable or not.
private bool GetCanSeekCore() => _cachedFileType != -1
? (FileHandleType)_cachedFileType == FileHandleType.RegularFile
: Interop.Kernel32.GetFileType(this) == Interop.Kernel32.FileTypes.FILE_TYPE_DISK;

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the benchmark results show there is no performance regression (actually, even a small improvement):

BenchmarkDotNet v0.16.0-preview.1, Windows 11 (10.0.26100.33158/24H2/2024Update/HudsonValley) (Hyper-V)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 8 logical and 4 physical cores
Memory: 31.99 GB Total, 27.1 GB Available
.NET SDK 11.0.100-rc.1.26410.104
[Host] : .NET 11.0.0 (11.0.0-rc.1.26410.104, 11.0.26.41104), X64 RyuJIT x86-64-v4
MethodToolchainMeanErrorRatioAllocatedAlloc Ratio
ReadAllBytesmain25.05 μs0.483 μs1.021104 B1.00
ReadAllBytesPR #13207724.62 μs0.467 μs1.001104 B1.00
ReadAllBytesAsyncmain48.17 μs0.702 μs1.061624 B1.00
ReadAllBytesAsyncPR #13207745.58 μs0.901 μs1.001624 B1.00
OpenAndCanSeekmain11.23 μs0.112 μs1.01248 B1.00
OpenAndCanSeekPR #13207711.13 μs0.103 μs1.00248 B1.00

Full logs

@adamsitnikadamsitnik changed the title Fix FileStream initialization for write-only named pipesEnsure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipesAug 11, 2026
@adamsitnikadamsitnik added this to the 11.0.0 milestone Aug 11, 2026
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g networking test failures are unrelated

@adamsitnik
adamsitnik merged commit c82af78 into mainAug 11, 2026
130 of 132 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-regression-test-pipe-access-outbound branch August 11, 2026 16:25
@dotnet-milestone-botdotnet-milestone-botBot modified the milestones: 11.0.0, 11.0-rc1Aug 12, 2026
jozkee added a commit that referenced this pull request Aug 12, 2026
Follow-up to #132077.
## Summary
- Determine Windows `SafeFileHandle.CanSeek` directly from the raw
`GetFileType` result instead of the cached, refined
`SafeFileHandle.Type` value.
- Add symbolic-link regression tests covering `Type` access both before
and after `FileStream` evaluates `CanSeek`.
## Rationale
For handles opened on a symbolic link, Windows reports `FILE_TYPE_DISK`,
while `SafeFileHandle.Type` refines that to `SymbolicLink`. As a result,
#132077 could cache different `CanSeek` values depending on whether
`Type` was queried before constructing the `FileStream`. Using the raw
file type restores access-order-independent behavior while retaining the
write-only named-pipe fix.
## Validation
- `.\build.cmd clr.corelib` — succeeded with 0 warnings and 0 errors.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedByType` — passed.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedBySubsequentTypeAccess`
— passed.
- `FileStream_WriteOnlyNamedPipe_CanSeek_IsAsync` — 2 cases passed.
No baseline build was run.
> [!NOTE]
> This pull request description was generated with GitHub Copilot.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FileStream over write-only overlapped named pipe handle throws UnauthorizedAccessException on .NET 11 (regression from .NET 10)

4 participants

@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes by Copilot · Pull Request #132077 · dotnet/runtime · GitHub
Skip to content

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes - #132077

Merged
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound
Aug 11, 2026
Merged

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes#132077
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound

Conversation

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

fixes#131503

CopilotAIand others added 2 commits August 10, 2026 12:51
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 adjusts how SafeFileHandle.CanSeek is determined and cached so FileStream construction works reliably on Windows for handles that can’t be safely probed via file-type detection (notably write-only named pipes), and adds a regression test to cover the scenario.

Changes:

  • Centralizes SafeFileHandle.CanSeek caching state in the shared SafeFileHandle partial.
  • Updates Windows seekability probing to use SetFilePointerEx(..., 0, FILE_CURRENT) and cache the result.
  • Adds a Windows test validating FileStream construction over a write-only named-pipe handle (sync and overlapped) reports CanSeek == false and preserves IsAsync.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.csAdds a regression theory for FileStream over write-only named-pipe handles (sync/overlapped).
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.csImplements Windows seekability probing via SetFilePointerEx and caches the result.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.csRemoves the per-Unix CanSeek member/field now that caching is centralized.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.csAdds shared _canSeek cache and CanSeek property used by platform-specific implementations.
Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:98

  • After switching to Interop.Kernel32.CreateNamedPipeFileHandle, the local CreateNamedPipe P/Invoke is redundant and should be removed to avoid carrying duplicate interop declarations.
 [DllImport("kernel32.dll", EntryPoint = "CreateNamedPipeW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateNamedPipe(
string pipeName,
int openMode,
int pipeMode,

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:03

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

Addressed the requested review feedback in 17a1774.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:76

  • SECURITY_ATTRIBUTES is passed by ref with nLength == 0 and the pipe name omits the LOCAL namespace. Initializing SECURITY_ATTRIBUTES via the helper and using the \\.\pipe\LOCAL\... naming pattern (as used by SafeFileHandle.CreateAnonymousPipe) makes this test more robust on AppContainer scenarios and avoids relying on an uninitialized SECURITY_ATTRIBUTES layout.
 Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default;
using SafeFileHandle handle = Interop.Kernel32.CreateNamedPipeFileHandle(
$@"\\.\pipe\{Guid.NewGuid():N}",

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback and fix the test project build

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:54

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback and fix the test project build

Addressed in 6cbbf8f. The test now uses only PIPE_ACCESS_OUTBOUND, and the Windows test project includes the required shared named-pipe interop sources.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@adamsitnik
adamsitnik marked this pull request as ready for review August 10, 2026 15:11
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:75

  • The test creates the named pipe using the plain \\.\pipe\... namespace. In AppContainer environments Windows requires the \\.\pipe\LOCAL\ prefix (see SafeFileHandle.Windows.cs where CreateAnonymousPipe uses \\.\pipe\LOCAL\... for this reason), so this test can fail under those runs.

Consider using the LOCAL namespace unconditionally (it works both inside and outside AppContainer) to keep the test robust across CI environments.

 $@"\\.\pipe\{Guid.NewGuid():N}",

CopilotAI review requested due to automatic review settings August 10, 2026 17:22
@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs:342

  • GetCanSeekCore currently treats any FILE_TYPE_DISK handle as seekable when _cachedFileType is unset, which is broader than the previous Type == RegularFile behavior and can permanently cache an incorrect true result (e.g., for directory/symlink handles) without ever consulting the more specific file-type logic. It also doesn’t match the PR description’s claim of probing seekability with SetFilePointerEx. Consider keeping the cheap pipe-safe GetFileType gate, but use the existing SetFilePointerEx probe for disk handles (and fast-path known-regular files opened via SafeFileHandle.Open).
 // That is why we use the cached file type (if available), and if not available, we use GetFileType to determine whether the file is seekable or not.
private bool GetCanSeekCore() => _cachedFileType != -1
? (FileHandleType)_cachedFileType == FileHandleType.RegularFile
: Interop.Kernel32.GetFileType(this) == Interop.Kernel32.FileTypes.FILE_TYPE_DISK;

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the benchmark results show there is no performance regression (actually, even a small improvement):

BenchmarkDotNet v0.16.0-preview.1, Windows 11 (10.0.26100.33158/24H2/2024Update/HudsonValley) (Hyper-V)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 8 logical and 4 physical cores
Memory: 31.99 GB Total, 27.1 GB Available
.NET SDK 11.0.100-rc.1.26410.104
[Host] : .NET 11.0.0 (11.0.0-rc.1.26410.104, 11.0.26.41104), X64 RyuJIT x86-64-v4
MethodToolchainMeanErrorRatioAllocatedAlloc Ratio
ReadAllBytesmain25.05 μs0.483 μs1.021104 B1.00
ReadAllBytesPR #13207724.62 μs0.467 μs1.001104 B1.00
ReadAllBytesAsyncmain48.17 μs0.702 μs1.061624 B1.00
ReadAllBytesAsyncPR #13207745.58 μs0.901 μs1.001624 B1.00
OpenAndCanSeekmain11.23 μs0.112 μs1.01248 B1.00
OpenAndCanSeekPR #13207711.13 μs0.103 μs1.00248 B1.00

Full logs

@adamsitnikadamsitnik changed the title Fix FileStream initialization for write-only named pipesEnsure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipesAug 11, 2026
@adamsitnikadamsitnik added this to the 11.0.0 milestone Aug 11, 2026
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g networking test failures are unrelated

@adamsitnik
adamsitnik merged commit c82af78 into mainAug 11, 2026
130 of 132 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-regression-test-pipe-access-outbound branch August 11, 2026 16:25
@dotnet-milestone-botdotnet-milestone-botBot modified the milestones: 11.0.0, 11.0-rc1Aug 12, 2026
jozkee added a commit that referenced this pull request Aug 12, 2026
Follow-up to #132077.
## Summary
- Determine Windows `SafeFileHandle.CanSeek` directly from the raw
`GetFileType` result instead of the cached, refined
`SafeFileHandle.Type` value.
- Add symbolic-link regression tests covering `Type` access both before
and after `FileStream` evaluates `CanSeek`.
## Rationale
For handles opened on a symbolic link, Windows reports `FILE_TYPE_DISK`,
while `SafeFileHandle.Type` refines that to `SymbolicLink`. As a result,
#132077 could cache different `CanSeek` values depending on whether
`Type` was queried before constructing the `FileStream`. Using the raw
file type restores access-order-independent behavior while retaining the
write-only named-pipe fix.
## Validation
- `.\build.cmd clr.corelib` — succeeded with 0 warnings and 0 errors.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedByType` — passed.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedBySubsequentTypeAccess`
— passed.
- `FileStream_WriteOnlyNamedPipe_CanSeek_IsAsync` — 2 cases passed.
No baseline build was run.
> [!NOTE]
> This pull request description was generated with GitHub Copilot.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FileStream over write-only overlapped named pipe handle throws UnauthorizedAccessException on .NET 11 (regression from .NET 10)

4 participants

@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes by Copilot · Pull Request #132077 · dotnet/runtime · GitHub
Skip to content

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes - #132077

Merged
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound
Aug 11, 2026
Merged

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes#132077
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound

Conversation

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

fixes#131503

CopilotAIand others added 2 commits August 10, 2026 12:51
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 adjusts how SafeFileHandle.CanSeek is determined and cached so FileStream construction works reliably on Windows for handles that can’t be safely probed via file-type detection (notably write-only named pipes), and adds a regression test to cover the scenario.

Changes:

  • Centralizes SafeFileHandle.CanSeek caching state in the shared SafeFileHandle partial.
  • Updates Windows seekability probing to use SetFilePointerEx(..., 0, FILE_CURRENT) and cache the result.
  • Adds a Windows test validating FileStream construction over a write-only named-pipe handle (sync and overlapped) reports CanSeek == false and preserves IsAsync.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.csAdds a regression theory for FileStream over write-only named-pipe handles (sync/overlapped).
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.csImplements Windows seekability probing via SetFilePointerEx and caches the result.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.csRemoves the per-Unix CanSeek member/field now that caching is centralized.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.csAdds shared _canSeek cache and CanSeek property used by platform-specific implementations.
Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:98

  • After switching to Interop.Kernel32.CreateNamedPipeFileHandle, the local CreateNamedPipe P/Invoke is redundant and should be removed to avoid carrying duplicate interop declarations.
 [DllImport("kernel32.dll", EntryPoint = "CreateNamedPipeW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateNamedPipe(
string pipeName,
int openMode,
int pipeMode,

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:03

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

Addressed the requested review feedback in 17a1774.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:76

  • SECURITY_ATTRIBUTES is passed by ref with nLength == 0 and the pipe name omits the LOCAL namespace. Initializing SECURITY_ATTRIBUTES via the helper and using the \\.\pipe\LOCAL\... naming pattern (as used by SafeFileHandle.CreateAnonymousPipe) makes this test more robust on AppContainer scenarios and avoids relying on an uninitialized SECURITY_ATTRIBUTES layout.
 Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default;
using SafeFileHandle handle = Interop.Kernel32.CreateNamedPipeFileHandle(
$@"\\.\pipe\{Guid.NewGuid():N}",

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback and fix the test project build

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:54

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback and fix the test project build

Addressed in 6cbbf8f. The test now uses only PIPE_ACCESS_OUTBOUND, and the Windows test project includes the required shared named-pipe interop sources.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@adamsitnik
adamsitnik marked this pull request as ready for review August 10, 2026 15:11
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:75

  • The test creates the named pipe using the plain \\.\pipe\... namespace. In AppContainer environments Windows requires the \\.\pipe\LOCAL\ prefix (see SafeFileHandle.Windows.cs where CreateAnonymousPipe uses \\.\pipe\LOCAL\... for this reason), so this test can fail under those runs.

Consider using the LOCAL namespace unconditionally (it works both inside and outside AppContainer) to keep the test robust across CI environments.

 $@"\\.\pipe\{Guid.NewGuid():N}",

CopilotAI review requested due to automatic review settings August 10, 2026 17:22
@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs:342

  • GetCanSeekCore currently treats any FILE_TYPE_DISK handle as seekable when _cachedFileType is unset, which is broader than the previous Type == RegularFile behavior and can permanently cache an incorrect true result (e.g., for directory/symlink handles) without ever consulting the more specific file-type logic. It also doesn’t match the PR description’s claim of probing seekability with SetFilePointerEx. Consider keeping the cheap pipe-safe GetFileType gate, but use the existing SetFilePointerEx probe for disk handles (and fast-path known-regular files opened via SafeFileHandle.Open).
 // That is why we use the cached file type (if available), and if not available, we use GetFileType to determine whether the file is seekable or not.
private bool GetCanSeekCore() => _cachedFileType != -1
? (FileHandleType)_cachedFileType == FileHandleType.RegularFile
: Interop.Kernel32.GetFileType(this) == Interop.Kernel32.FileTypes.FILE_TYPE_DISK;

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the benchmark results show there is no performance regression (actually, even a small improvement):

BenchmarkDotNet v0.16.0-preview.1, Windows 11 (10.0.26100.33158/24H2/2024Update/HudsonValley) (Hyper-V)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 8 logical and 4 physical cores
Memory: 31.99 GB Total, 27.1 GB Available
.NET SDK 11.0.100-rc.1.26410.104
[Host] : .NET 11.0.0 (11.0.0-rc.1.26410.104, 11.0.26.41104), X64 RyuJIT x86-64-v4
MethodToolchainMeanErrorRatioAllocatedAlloc Ratio
ReadAllBytesmain25.05 μs0.483 μs1.021104 B1.00
ReadAllBytesPR #13207724.62 μs0.467 μs1.001104 B1.00
ReadAllBytesAsyncmain48.17 μs0.702 μs1.061624 B1.00
ReadAllBytesAsyncPR #13207745.58 μs0.901 μs1.001624 B1.00
OpenAndCanSeekmain11.23 μs0.112 μs1.01248 B1.00
OpenAndCanSeekPR #13207711.13 μs0.103 μs1.00248 B1.00

Full logs

@adamsitnikadamsitnik changed the title Fix FileStream initialization for write-only named pipesEnsure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipesAug 11, 2026
@adamsitnikadamsitnik added this to the 11.0.0 milestone Aug 11, 2026
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g networking test failures are unrelated

@adamsitnik
adamsitnik merged commit c82af78 into mainAug 11, 2026
130 of 132 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-regression-test-pipe-access-outbound branch August 11, 2026 16:25
@dotnet-milestone-botdotnet-milestone-botBot modified the milestones: 11.0.0, 11.0-rc1Aug 12, 2026
jozkee added a commit that referenced this pull request Aug 12, 2026
Follow-up to #132077.
## Summary
- Determine Windows `SafeFileHandle.CanSeek` directly from the raw
`GetFileType` result instead of the cached, refined
`SafeFileHandle.Type` value.
- Add symbolic-link regression tests covering `Type` access both before
and after `FileStream` evaluates `CanSeek`.
## Rationale
For handles opened on a symbolic link, Windows reports `FILE_TYPE_DISK`,
while `SafeFileHandle.Type` refines that to `SymbolicLink`. As a result,
#132077 could cache different `CanSeek` values depending on whether
`Type` was queried before constructing the `FileStream`. Using the raw
file type restores access-order-independent behavior while retaining the
write-only named-pipe fix.
## Validation
- `.\build.cmd clr.corelib` — succeeded with 0 warnings and 0 errors.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedByType` — passed.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedBySubsequentTypeAccess`
— passed.
- `FileStream_WriteOnlyNamedPipe_CanSeek_IsAsync` — 2 cases passed.
No baseline build was run.
> [!NOTE]
> This pull request description was generated with GitHub Copilot.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FileStream over write-only overlapped named pipe handle throws UnauthorizedAccessException on .NET 11 (regression from .NET 10)

4 participants

@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes by Copilot · Pull Request #132077 · dotnet/runtime · GitHub
Skip to content

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes - #132077

Merged
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound
Aug 11, 2026
Merged

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes#132077
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound

Conversation

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

fixes#131503

CopilotAIand others added 2 commits August 10, 2026 12:51
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 adjusts how SafeFileHandle.CanSeek is determined and cached so FileStream construction works reliably on Windows for handles that can’t be safely probed via file-type detection (notably write-only named pipes), and adds a regression test to cover the scenario.

Changes:

  • Centralizes SafeFileHandle.CanSeek caching state in the shared SafeFileHandle partial.
  • Updates Windows seekability probing to use SetFilePointerEx(..., 0, FILE_CURRENT) and cache the result.
  • Adds a Windows test validating FileStream construction over a write-only named-pipe handle (sync and overlapped) reports CanSeek == false and preserves IsAsync.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.csAdds a regression theory for FileStream over write-only named-pipe handles (sync/overlapped).
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.csImplements Windows seekability probing via SetFilePointerEx and caches the result.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.csRemoves the per-Unix CanSeek member/field now that caching is centralized.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.csAdds shared _canSeek cache and CanSeek property used by platform-specific implementations.
Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:98

  • After switching to Interop.Kernel32.CreateNamedPipeFileHandle, the local CreateNamedPipe P/Invoke is redundant and should be removed to avoid carrying duplicate interop declarations.
 [DllImport("kernel32.dll", EntryPoint = "CreateNamedPipeW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateNamedPipe(
string pipeName,
int openMode,
int pipeMode,

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:03

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

Addressed the requested review feedback in 17a1774.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:76

  • SECURITY_ATTRIBUTES is passed by ref with nLength == 0 and the pipe name omits the LOCAL namespace. Initializing SECURITY_ATTRIBUTES via the helper and using the \\.\pipe\LOCAL\... naming pattern (as used by SafeFileHandle.CreateAnonymousPipe) makes this test more robust on AppContainer scenarios and avoids relying on an uninitialized SECURITY_ATTRIBUTES layout.
 Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default;
using SafeFileHandle handle = Interop.Kernel32.CreateNamedPipeFileHandle(
$@"\\.\pipe\{Guid.NewGuid():N}",

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback and fix the test project build

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:54

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback and fix the test project build

Addressed in 6cbbf8f. The test now uses only PIPE_ACCESS_OUTBOUND, and the Windows test project includes the required shared named-pipe interop sources.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@adamsitnik
adamsitnik marked this pull request as ready for review August 10, 2026 15:11
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:75

  • The test creates the named pipe using the plain \\.\pipe\... namespace. In AppContainer environments Windows requires the \\.\pipe\LOCAL\ prefix (see SafeFileHandle.Windows.cs where CreateAnonymousPipe uses \\.\pipe\LOCAL\... for this reason), so this test can fail under those runs.

Consider using the LOCAL namespace unconditionally (it works both inside and outside AppContainer) to keep the test robust across CI environments.

 $@"\\.\pipe\{Guid.NewGuid():N}",

CopilotAI review requested due to automatic review settings August 10, 2026 17:22
@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs:342

  • GetCanSeekCore currently treats any FILE_TYPE_DISK handle as seekable when _cachedFileType is unset, which is broader than the previous Type == RegularFile behavior and can permanently cache an incorrect true result (e.g., for directory/symlink handles) without ever consulting the more specific file-type logic. It also doesn’t match the PR description’s claim of probing seekability with SetFilePointerEx. Consider keeping the cheap pipe-safe GetFileType gate, but use the existing SetFilePointerEx probe for disk handles (and fast-path known-regular files opened via SafeFileHandle.Open).
 // That is why we use the cached file type (if available), and if not available, we use GetFileType to determine whether the file is seekable or not.
private bool GetCanSeekCore() => _cachedFileType != -1
? (FileHandleType)_cachedFileType == FileHandleType.RegularFile
: Interop.Kernel32.GetFileType(this) == Interop.Kernel32.FileTypes.FILE_TYPE_DISK;

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the benchmark results show there is no performance regression (actually, even a small improvement):

BenchmarkDotNet v0.16.0-preview.1, Windows 11 (10.0.26100.33158/24H2/2024Update/HudsonValley) (Hyper-V)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 8 logical and 4 physical cores
Memory: 31.99 GB Total, 27.1 GB Available
.NET SDK 11.0.100-rc.1.26410.104
[Host] : .NET 11.0.0 (11.0.0-rc.1.26410.104, 11.0.26.41104), X64 RyuJIT x86-64-v4
MethodToolchainMeanErrorRatioAllocatedAlloc Ratio
ReadAllBytesmain25.05 μs0.483 μs1.021104 B1.00
ReadAllBytesPR #13207724.62 μs0.467 μs1.001104 B1.00
ReadAllBytesAsyncmain48.17 μs0.702 μs1.061624 B1.00
ReadAllBytesAsyncPR #13207745.58 μs0.901 μs1.001624 B1.00
OpenAndCanSeekmain11.23 μs0.112 μs1.01248 B1.00
OpenAndCanSeekPR #13207711.13 μs0.103 μs1.00248 B1.00

Full logs

@adamsitnikadamsitnik changed the title Fix FileStream initialization for write-only named pipesEnsure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipesAug 11, 2026
@adamsitnikadamsitnik added this to the 11.0.0 milestone Aug 11, 2026
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g networking test failures are unrelated

@adamsitnik
adamsitnik merged commit c82af78 into mainAug 11, 2026
130 of 132 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-regression-test-pipe-access-outbound branch August 11, 2026 16:25
@dotnet-milestone-botdotnet-milestone-botBot modified the milestones: 11.0.0, 11.0-rc1Aug 12, 2026
jozkee added a commit that referenced this pull request Aug 12, 2026
Follow-up to #132077.
## Summary
- Determine Windows `SafeFileHandle.CanSeek` directly from the raw
`GetFileType` result instead of the cached, refined
`SafeFileHandle.Type` value.
- Add symbolic-link regression tests covering `Type` access both before
and after `FileStream` evaluates `CanSeek`.
## Rationale
For handles opened on a symbolic link, Windows reports `FILE_TYPE_DISK`,
while `SafeFileHandle.Type` refines that to `SymbolicLink`. As a result,
#132077 could cache different `CanSeek` values depending on whether
`Type` was queried before constructing the `FileStream`. Using the raw
file type restores access-order-independent behavior while retaining the
write-only named-pipe fix.
## Validation
- `.\build.cmd clr.corelib` — succeeded with 0 warnings and 0 errors.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedByType` — passed.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedBySubsequentTypeAccess`
— passed.
- `FileStream_WriteOnlyNamedPipe_CanSeek_IsAsync` — 2 cases passed.
No baseline build was run.
> [!NOTE]
> This pull request description was generated with GitHub Copilot.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FileStream over write-only overlapped named pipe handle throws UnauthorizedAccessException on .NET 11 (regression from .NET 10)

4 participants

@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes by Copilot · Pull Request #132077 · dotnet/runtime · GitHub
Skip to content

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes - #132077

Merged
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound
Aug 11, 2026
Merged

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes#132077
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound

Conversation

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

fixes#131503

CopilotAIand others added 2 commits August 10, 2026 12:51
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 adjusts how SafeFileHandle.CanSeek is determined and cached so FileStream construction works reliably on Windows for handles that can’t be safely probed via file-type detection (notably write-only named pipes), and adds a regression test to cover the scenario.

Changes:

  • Centralizes SafeFileHandle.CanSeek caching state in the shared SafeFileHandle partial.
  • Updates Windows seekability probing to use SetFilePointerEx(..., 0, FILE_CURRENT) and cache the result.
  • Adds a Windows test validating FileStream construction over a write-only named-pipe handle (sync and overlapped) reports CanSeek == false and preserves IsAsync.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.csAdds a regression theory for FileStream over write-only named-pipe handles (sync/overlapped).
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.csImplements Windows seekability probing via SetFilePointerEx and caches the result.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.csRemoves the per-Unix CanSeek member/field now that caching is centralized.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.csAdds shared _canSeek cache and CanSeek property used by platform-specific implementations.
Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:98

  • After switching to Interop.Kernel32.CreateNamedPipeFileHandle, the local CreateNamedPipe P/Invoke is redundant and should be removed to avoid carrying duplicate interop declarations.
 [DllImport("kernel32.dll", EntryPoint = "CreateNamedPipeW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateNamedPipe(
string pipeName,
int openMode,
int pipeMode,

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:03

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

Addressed the requested review feedback in 17a1774.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:76

  • SECURITY_ATTRIBUTES is passed by ref with nLength == 0 and the pipe name omits the LOCAL namespace. Initializing SECURITY_ATTRIBUTES via the helper and using the \\.\pipe\LOCAL\... naming pattern (as used by SafeFileHandle.CreateAnonymousPipe) makes this test more robust on AppContainer scenarios and avoids relying on an uninitialized SECURITY_ATTRIBUTES layout.
 Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default;
using SafeFileHandle handle = Interop.Kernel32.CreateNamedPipeFileHandle(
$@"\\.\pipe\{Guid.NewGuid():N}",

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback and fix the test project build

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:54

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback and fix the test project build

Addressed in 6cbbf8f. The test now uses only PIPE_ACCESS_OUTBOUND, and the Windows test project includes the required shared named-pipe interop sources.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@adamsitnik
adamsitnik marked this pull request as ready for review August 10, 2026 15:11
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:75

  • The test creates the named pipe using the plain \\.\pipe\... namespace. In AppContainer environments Windows requires the \\.\pipe\LOCAL\ prefix (see SafeFileHandle.Windows.cs where CreateAnonymousPipe uses \\.\pipe\LOCAL\... for this reason), so this test can fail under those runs.

Consider using the LOCAL namespace unconditionally (it works both inside and outside AppContainer) to keep the test robust across CI environments.

 $@"\\.\pipe\{Guid.NewGuid():N}",

CopilotAI review requested due to automatic review settings August 10, 2026 17:22
@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs:342

  • GetCanSeekCore currently treats any FILE_TYPE_DISK handle as seekable when _cachedFileType is unset, which is broader than the previous Type == RegularFile behavior and can permanently cache an incorrect true result (e.g., for directory/symlink handles) without ever consulting the more specific file-type logic. It also doesn’t match the PR description’s claim of probing seekability with SetFilePointerEx. Consider keeping the cheap pipe-safe GetFileType gate, but use the existing SetFilePointerEx probe for disk handles (and fast-path known-regular files opened via SafeFileHandle.Open).
 // That is why we use the cached file type (if available), and if not available, we use GetFileType to determine whether the file is seekable or not.
private bool GetCanSeekCore() => _cachedFileType != -1
? (FileHandleType)_cachedFileType == FileHandleType.RegularFile
: Interop.Kernel32.GetFileType(this) == Interop.Kernel32.FileTypes.FILE_TYPE_DISK;

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the benchmark results show there is no performance regression (actually, even a small improvement):

BenchmarkDotNet v0.16.0-preview.1, Windows 11 (10.0.26100.33158/24H2/2024Update/HudsonValley) (Hyper-V)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 8 logical and 4 physical cores
Memory: 31.99 GB Total, 27.1 GB Available
.NET SDK 11.0.100-rc.1.26410.104
[Host] : .NET 11.0.0 (11.0.0-rc.1.26410.104, 11.0.26.41104), X64 RyuJIT x86-64-v4
MethodToolchainMeanErrorRatioAllocatedAlloc Ratio
ReadAllBytesmain25.05 μs0.483 μs1.021104 B1.00
ReadAllBytesPR #13207724.62 μs0.467 μs1.001104 B1.00
ReadAllBytesAsyncmain48.17 μs0.702 μs1.061624 B1.00
ReadAllBytesAsyncPR #13207745.58 μs0.901 μs1.001624 B1.00
OpenAndCanSeekmain11.23 μs0.112 μs1.01248 B1.00
OpenAndCanSeekPR #13207711.13 μs0.103 μs1.00248 B1.00

Full logs

@adamsitnikadamsitnik changed the title Fix FileStream initialization for write-only named pipesEnsure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipesAug 11, 2026
@adamsitnikadamsitnik added this to the 11.0.0 milestone Aug 11, 2026
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g networking test failures are unrelated

@adamsitnik
adamsitnik merged commit c82af78 into mainAug 11, 2026
130 of 132 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-regression-test-pipe-access-outbound branch August 11, 2026 16:25
@dotnet-milestone-botdotnet-milestone-botBot modified the milestones: 11.0.0, 11.0-rc1Aug 12, 2026
jozkee added a commit that referenced this pull request Aug 12, 2026
Follow-up to #132077.
## Summary
- Determine Windows `SafeFileHandle.CanSeek` directly from the raw
`GetFileType` result instead of the cached, refined
`SafeFileHandle.Type` value.
- Add symbolic-link regression tests covering `Type` access both before
and after `FileStream` evaluates `CanSeek`.
## Rationale
For handles opened on a symbolic link, Windows reports `FILE_TYPE_DISK`,
while `SafeFileHandle.Type` refines that to `SymbolicLink`. As a result,
#132077 could cache different `CanSeek` values depending on whether
`Type` was queried before constructing the `FileStream`. Using the raw
file type restores access-order-independent behavior while retaining the
write-only named-pipe fix.
## Validation
- `.\build.cmd clr.corelib` — succeeded with 0 warnings and 0 errors.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedByType` — passed.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedBySubsequentTypeAccess`
— passed.
- `FileStream_WriteOnlyNamedPipe_CanSeek_IsAsync` — 2 cases passed.
No baseline build was run.
> [!NOTE]
> This pull request description was generated with GitHub Copilot.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FileStream over write-only overlapped named pipe handle throws UnauthorizedAccessException on .NET 11 (regression from .NET 10)

4 participants

@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes by Copilot · Pull Request #132077 · dotnet/runtime · GitHub
Skip to content

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes - #132077

Merged
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound
Aug 11, 2026
Merged

Ensure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipes#132077
adamsitnik merged 6 commits into
mainfrom
copilot/fix-regression-test-pipe-access-outbound

Conversation

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

fixes#131503

CopilotAIand others added 2 commits August 10, 2026 12:51
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 adjusts how SafeFileHandle.CanSeek is determined and cached so FileStream construction works reliably on Windows for handles that can’t be safely probed via file-type detection (notably write-only named pipes), and adds a regression test to cover the scenario.

Changes:

  • Centralizes SafeFileHandle.CanSeek caching state in the shared SafeFileHandle partial.
  • Updates Windows seekability probing to use SetFilePointerEx(..., 0, FILE_CURRENT) and cache the result.
  • Adds a Windows test validating FileStream construction over a write-only named-pipe handle (sync and overlapped) reports CanSeek == false and preserves IsAsync.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.csAdds a regression theory for FileStream over write-only named-pipe handles (sync/overlapped).
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.csImplements Windows seekability probing via SetFilePointerEx and caches the result.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.csRemoves the per-Unix CanSeek member/field now that caching is centralized.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.csAdds shared _canSeek cache and CanSeek property used by platform-specific implementations.
Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:98

  • After switching to Interop.Kernel32.CreateNamedPipeFileHandle, the local CreateNamedPipe P/Invoke is redundant and should be removed to avoid carrying duplicate interop declarations.
 [DllImport("kernel32.dll", EntryPoint = "CreateNamedPipeW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateNamedPipe(
string pipeName,
int openMode,
int pipeMode,

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:03

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

Addressed the requested review feedback in 17a1774.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:76

  • SECURITY_ATTRIBUTES is passed by ref with nLength == 0 and the pipe name omits the LOCAL namespace. Initializing SECURITY_ATTRIBUTES via the helper and using the \\.\pipe\LOCAL\... naming pattern (as used by SafeFileHandle.CreateAnonymousPipe) makes this test more robust on AppContainer scenarios and avoids relying on an uninitialized SECURITY_ATTRIBUTES layout.
 Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default;
using SafeFileHandle handle = Interop.Kernel32.CreateNamedPipeFileHandle(
$@"\\.\pipe\{Guid.NewGuid():N}",

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback and fix the test project build

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 10, 2026 14:54

CopilotAI commented Aug 10, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback and fix the test project build

Addressed in 6cbbf8f. The test now uses only PIPE_ACCESS_OUTBOUND, and the Windows test project includes the required shared named-pipe interop sources.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@adamsitnik
adamsitnik marked this pull request as ready for review August 10, 2026 15:11
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.Windows.cs:75

  • The test creates the named pipe using the plain \\.\pipe\... namespace. In AppContainer environments Windows requires the \\.\pipe\LOCAL\ prefix (see SafeFileHandle.Windows.cs where CreateAnonymousPipe uses \\.\pipe\LOCAL\... for this reason), so this test can fail under those runs.

Consider using the LOCAL namespace unconditionally (it works both inside and outside AppContainer) to keep the test robust across CI environments.

 $@"\\.\pipe\{Guid.NewGuid():N}",

CopilotAI review requested due to automatic review settings August 10, 2026 17:22
@adamsitnik

Copy link
Copy Markdown
Member

@EgorBot -windows_intel

usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Running;BenchmarkSwitcher.FromAssembly(typeof(Benchmarks).Assembly).Run(args);[MemoryDiagnoser]publicclassBenchmarks{privatestring?_filePath;[GlobalSetup]publicvoidSetup(){_filePath=Path.GetTempFileName();File.WriteAllBytes(_filePath,newbyte[1_000]);}[GlobalCleanup]publicvoidCleanup()=>File.Delete(_filePath!);[Benchmark]publicbyte[]ReadAllBytes()=>File.ReadAllBytes(_filePath!);[Benchmark]publicTaskReadAllBytesAsync()=>File.ReadAllBytesAsync(_filePath!);[Benchmark]publicboolOpenAndCanSeek(){usingFileStreamhandle=File.OpenRead(_filePath!);returnhandle.CanSeek;}}

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs:342

  • GetCanSeekCore currently treats any FILE_TYPE_DISK handle as seekable when _cachedFileType is unset, which is broader than the previous Type == RegularFile behavior and can permanently cache an incorrect true result (e.g., for directory/symlink handles) without ever consulting the more specific file-type logic. It also doesn’t match the PR description’s claim of probing seekability with SetFilePointerEx. Consider keeping the cheap pipe-safe GetFileType gate, but use the existing SetFilePointerEx probe for disk handles (and fast-path known-regular files opened via SafeFileHandle.Open).
 // That is why we use the cached file type (if available), and if not available, we use GetFileType to determine whether the file is seekable or not.
private bool GetCanSeekCore() => _cachedFileType != -1
? (FileHandleType)_cachedFileType == FileHandleType.RegularFile
: Interop.Kernel32.GetFileType(this) == Interop.Kernel32.FileTypes.FILE_TYPE_DISK;

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the benchmark results show there is no performance regression (actually, even a small improvement):

BenchmarkDotNet v0.16.0-preview.1, Windows 11 (10.0.26100.33158/24H2/2024Update/HudsonValley) (Hyper-V)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 8 logical and 4 physical cores
Memory: 31.99 GB Total, 27.1 GB Available
.NET SDK 11.0.100-rc.1.26410.104
[Host] : .NET 11.0.0 (11.0.0-rc.1.26410.104, 11.0.26.41104), X64 RyuJIT x86-64-v4
MethodToolchainMeanErrorRatioAllocatedAlloc Ratio
ReadAllBytesmain25.05 μs0.483 μs1.021104 B1.00
ReadAllBytesPR #13207724.62 μs0.467 μs1.001104 B1.00
ReadAllBytesAsyncmain48.17 μs0.702 μs1.061624 B1.00
ReadAllBytesAsyncPR #13207745.58 μs0.901 μs1.001624 B1.00
OpenAndCanSeekmain11.23 μs0.112 μs1.01248 B1.00
OpenAndCanSeekPR #13207711.13 μs0.103 μs1.00248 B1.00

Full logs

@adamsitnikadamsitnik changed the title Fix FileStream initialization for write-only named pipesEnsure FileStream.CanSeek works for PIPE_ACCESS_OUTBOUND pipesAug 11, 2026
@adamsitnikadamsitnik added this to the 11.0.0 milestone Aug 11, 2026
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g networking test failures are unrelated

@adamsitnik
adamsitnik merged commit c82af78 into mainAug 11, 2026
130 of 132 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-regression-test-pipe-access-outbound branch August 11, 2026 16:25
@dotnet-milestone-botdotnet-milestone-botBot modified the milestones: 11.0.0, 11.0-rc1Aug 12, 2026
jozkee added a commit that referenced this pull request Aug 12, 2026
Follow-up to #132077.
## Summary
- Determine Windows `SafeFileHandle.CanSeek` directly from the raw
`GetFileType` result instead of the cached, refined
`SafeFileHandle.Type` value.
- Add symbolic-link regression tests covering `Type` access both before
and after `FileStream` evaluates `CanSeek`.
## Rationale
For handles opened on a symbolic link, Windows reports `FILE_TYPE_DISK`,
while `SafeFileHandle.Type` refines that to `SymbolicLink`. As a result,
#132077 could cache different `CanSeek` values depending on whether
`Type` was queried before constructing the `FileStream`. Using the raw
file type restores access-order-independent behavior while retaining the
write-only named-pipe fix.
## Validation
- `.\build.cmd clr.corelib` — succeeded with 0 warnings and 0 errors.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedByType` — passed.
- `FileStream_SymbolicLink_CanSeek_IsNotAffectedBySubsequentTypeAccess`
— passed.
- `FileStream_WriteOnlyNamedPipe_CanSeek_IsAsync` — 2 cases passed.
No baseline build was run.
> [!NOTE]
> This pull request description was generated with GitHub Copilot.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FileStream over write-only overlapped named pipe handle throws UnauthorizedAccessException on .NET 11 (regression from .NET 10)

4 participants

@adamsitnik@jkotas