Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file - #126844

Merged
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug
Apr 20, 2026
Merged

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file#126844
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug

Conversation

CopilotAI commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Reverts all System.Console source changes from PR #125512 (which introduced RandomAccess.Read/Write based I/O) back to the original Interop.Sys.Read/Write implementation. The FileStream-based approach will be revisited separately.

Adds regression tests that verify Console.OpenStandardInput().CopyTo() and Console.OpenStandardOutput().Write() work correctly when stdin/stdout is redirected to a seekable file.

Description

  • Reverted ConsolePal.Unix.ConsoleStream.cs to use ConsolePal.Read() with Interop.Sys.Read
  • Reverted ConsolePal.Unix.cs to use Interop.Sys.Write with the full write loop (EPIPE, EAGAIN handling) and pointer-based UpdatedCachedCursorPosition
  • Reverted ConsolePal.Wasi.cs to use Interop.Sys.Read/Write directly
  • Restored Interop.Poll.cs, Interop.Read.cs, Interop.Write.cs references in System.Console.csproj for both WASI and Unix targets
  • Restored PR Support the FORCE_COLOR emerging standard in ConsoleUtils.EmitAnsiColorCodes #124492's FORCE_COLOR comment in ConsolePal.Unix.cs that was accidentally reverted along with PR Relax RandomAccess type requirements: make Read/Write methods work with non-seekable files #125512 changes
  • Added ConsoleHandles.cs to System.Console.Tests.csproj (was previously missing)
  • Added CanCopyStandardInputToStandardOutput test — verifies reading from seekable stdin via CopyTo
  • Added UnixConsoleStream_SeekableStdoutRedirection_WritesAllContent test — verifies writing to seekable stdout using two separate Write calls to ensure content is concatenated (not overwritten from offset 0), which properly covers the offset-based write regression

CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 17:27
CopilotAI linked an issue Apr 13, 2026 that may be closed by this pull request
@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.

RandomAccess.Read/Write use pread/pwrite syscalls which always operate at
a specified fileOffset. Passing fileOffset:0 for seekable files (e.g.,
regular files redirected as stdin/stdout) caused reads/writes to always
operate at position 0, resulting in infinite loops or incorrect output.
The fix creates a FileStream (with bufferSize:0) wrapping the handle when
the handle is seekable. FileStream uses OSFileStreamStrategy which tracks
the file position and advances it after each read/write, ensuring correct
sequential behavior for seekable files.
For non-seekable files (pipes, terminals), the existing RandomAccess-based
path is used, preserving cursor position tracking for terminals.
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:15
…g duplication
- Replace 'float for GC' FileStream approach with explicit _useFileStreamForIo bool field;
FileStream is always held and disposed deterministically
- Fix string duplication in stdout test by passing outputContent as RemoteExecutor arg
- Add try/catch around File.Delete in finally blocks
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:17
CopilotAI changed the title [WIP] Fix bug in UnixConsoleStream when working with seekable filesFix UnixConsoleStream when stdin/stdout is redirected to a seekable fileApr 13, 2026
CopilotAI requested a review from adamsitnikApril 13, 2026 18:20

@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 please address my feedback

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
…onsoleStream, simplify tests
- Remove _useFileStreamForIo field and extra comments; always use FileStream for I/O
- Change Write() in UnixConsoleStream to call WriteFromConsoleStream(_fileStream, buffer)
- Update WriteFromConsoleStream in ConsolePal.Unix.cs and ConsolePal.Wasi.cs to accept
FileStream instead of SafeFileHandle; use fs.Write(buffer) which handles both seekable
and non-seekable files correctly
- Rename SeekableStdinRedirection test to CanCopyStandardInputToStandardOutput and run on
all non-mobile platforms (not just AnyUnix); simplify via RemoteInvokeOptions.StartInfo
- Simplify SeekableStdoutRedirection test similarly; remove boilerplate try/catch
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/67a83dee-25ae-47d1-ae0f-b4aa1f18265f
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 14, 2026 06:53

CopilotAI commented Apr 14, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please address my feedback

Done in adb2b69. All review feedback addressed:

  • Removed _useFileStreamForIo and extra comments; FileStream is always used for all I/O (handles both seekable and non-seekable correctly)
  • Write() in UnixConsoleStream now calls WriteFromConsoleStream(_fileStream, buffer)
  • WriteFromConsoleStream in both ConsolePal.Unix.cs and ConsolePal.Wasi.cs updated to accept FileStream and call fs.Write(buffer)
  • Tests renamed/simplified and now run on all non-mobile platforms

@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

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
- Fix XML comment in ConsolePal.Wasi.cs Write(FileStream): fd → fs
- Remove _handle field from UnixConsoleStream; FileStream owns handle lifetime
- Remove Flush() override from UnixConsoleStream (base is a nop; bufferSize:0)
- Remove redundant [PlatformSpecific] from two new tests (RemoteExecutor handles it)
- Dispose stdoutHandle before WaitForExit so File.ReadAllText can open the file
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/ba3bd32e-023a-4160-bf27-f0ae05027d8d
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@adamsitnik

Copy link
Copy Markdown
Member

@jozkee@jkotas@stephentoub I would appreciate your review, as I would like to start a longer leave knowing that I leave no known bugs opened.

For context please refer to #126843

This PR is more or less a revert + tests that are going to ensure we are not going to introduce this bug again.

@adamsitnik
adamsitnik enabled auto-merge (squash) April 19, 2026 20:23

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 reverts recent System.Console Unix/WASI I/O changes that used RandomAccess.Read/Write back to the prior Interop.Sys.Read/Write implementation, and adds regression tests for redirected stdin/stdout to seekable files (to prevent hangs/incorrect output).

Changes:

  • Restore Interop.Sys.Read / Interop.Sys.Write-based console stream I/O on Unix and WASI (including the write loop with EPIPE/EAGAIN handling).
  • Add/enable regression tests covering seekable stdin and seekable stdout redirection scenarios.
  • Restore needed interop source inclusions in System.Console.csproj and include ConsoleHandles.cs in the test project.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
src/libraries/System.Console/tests/System.Console.Tests.csprojIncludes ConsoleHandles.cs in the test build.
src/libraries/System.Console/tests/ConsoleHandles.csAdds regression tests for seekable stdin/stdout redirection.
src/libraries/System.Console/src/System/ConsolePal.Wasi.csRestores Interop.Sys.Read/Write + write-loop behavior for WASI.
src/libraries/System.Console/src/System/ConsolePal.Unix.csRestores Interop.Sys.Read/Write + write-loop behavior and cursor-cache updates.
src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csSwitches console stream reads back to ConsolePal.Read (Interop-based).
src/libraries/System.Console/src/System.Console.csprojRe-adds interop source files (Poll/Read/Write) for Unix/WASI builds.

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
auto-merge was automatically disabled April 19, 2026 20:44

Head branch was pushed to by a user without write access

CopilotAI requested a review from adamsitnikApril 19, 2026 20:45
CopilotAI requested review from Copilot and removed request for CopilotApril 19, 2026 20:50
@adamsitnik
adamsitnik merged commit afd1456 into mainApr 20, 2026
91 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-unix-console-stream-bug branch April 20, 2026 05:57
@adamsitnik

Copy link
Copy Markdown
Member

/backport to release/11.0-preview4

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview4 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@adamsitnik backporting to release/11.0-preview4 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchCreating an empty commit: Initial planApplying: Fix UnixConsoleStream to handle seekable files correctlyUsing index info to reconstruct a base tree...M	src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csM	src/libraries/System.Console/tests/ConsoleHandles.csM	src/libraries/System.Console/tests/System.Console.Tests.csprojFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csCONFLICT (content): Merge conflict in src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csAuto-merging src/libraries/System.Console/tests/ConsoleHandles.csCONFLICT (content): Merge conflict in src/libraries/System.Console/tests/ConsoleHandles.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0002 Fix UnixConsoleStream to handle seekable files correctlyError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@adamsitnik

Copy link
Copy Markdown
Member

I am stupid, it was merged before P4 snap so it's already there...

@adamsitnikadamsitnik changed the title Add tests for UnixConsoleStream when stdin/stdout is redirected to a seekable fileFix UnixConsoleStream regression when stdin/stdout is redirected to a seekable fileMay 5, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug in UnixConsoleStream when working with seekable files

4 participants

@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n 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;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file - #126844

Merged
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug
Apr 20, 2026
Merged

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file#126844
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug

Conversation

CopilotAI commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Reverts all System.Console source changes from PR #125512 (which introduced RandomAccess.Read/Write based I/O) back to the original Interop.Sys.Read/Write implementation. The FileStream-based approach will be revisited separately.

Adds regression tests that verify Console.OpenStandardInput().CopyTo() and Console.OpenStandardOutput().Write() work correctly when stdin/stdout is redirected to a seekable file.

Description

  • Reverted ConsolePal.Unix.ConsoleStream.cs to use ConsolePal.Read() with Interop.Sys.Read
  • Reverted ConsolePal.Unix.cs to use Interop.Sys.Write with the full write loop (EPIPE, EAGAIN handling) and pointer-based UpdatedCachedCursorPosition
  • Reverted ConsolePal.Wasi.cs to use Interop.Sys.Read/Write directly
  • Restored Interop.Poll.cs, Interop.Read.cs, Interop.Write.cs references in System.Console.csproj for both WASI and Unix targets
  • Restored PR Support the FORCE_COLOR emerging standard in ConsoleUtils.EmitAnsiColorCodes #124492's FORCE_COLOR comment in ConsolePal.Unix.cs that was accidentally reverted along with PR Relax RandomAccess type requirements: make Read/Write methods work with non-seekable files #125512 changes
  • Added ConsoleHandles.cs to System.Console.Tests.csproj (was previously missing)
  • Added CanCopyStandardInputToStandardOutput test — verifies reading from seekable stdin via CopyTo
  • Added UnixConsoleStream_SeekableStdoutRedirection_WritesAllContent test — verifies writing to seekable stdout using two separate Write calls to ensure content is concatenated (not overwritten from offset 0), which properly covers the offset-based write regression

CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 17:27
CopilotAI linked an issue Apr 13, 2026 that may be closed by this pull request
@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.

RandomAccess.Read/Write use pread/pwrite syscalls which always operate at
a specified fileOffset. Passing fileOffset:0 for seekable files (e.g.,
regular files redirected as stdin/stdout) caused reads/writes to always
operate at position 0, resulting in infinite loops or incorrect output.
The fix creates a FileStream (with bufferSize:0) wrapping the handle when
the handle is seekable. FileStream uses OSFileStreamStrategy which tracks
the file position and advances it after each read/write, ensuring correct
sequential behavior for seekable files.
For non-seekable files (pipes, terminals), the existing RandomAccess-based
path is used, preserving cursor position tracking for terminals.
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:15
…g duplication
- Replace 'float for GC' FileStream approach with explicit _useFileStreamForIo bool field;
FileStream is always held and disposed deterministically
- Fix string duplication in stdout test by passing outputContent as RemoteExecutor arg
- Add try/catch around File.Delete in finally blocks
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:17
CopilotAI changed the title [WIP] Fix bug in UnixConsoleStream when working with seekable filesFix UnixConsoleStream when stdin/stdout is redirected to a seekable fileApr 13, 2026
CopilotAI requested a review from adamsitnikApril 13, 2026 18:20

@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 please address my feedback

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
…onsoleStream, simplify tests
- Remove _useFileStreamForIo field and extra comments; always use FileStream for I/O
- Change Write() in UnixConsoleStream to call WriteFromConsoleStream(_fileStream, buffer)
- Update WriteFromConsoleStream in ConsolePal.Unix.cs and ConsolePal.Wasi.cs to accept
FileStream instead of SafeFileHandle; use fs.Write(buffer) which handles both seekable
and non-seekable files correctly
- Rename SeekableStdinRedirection test to CanCopyStandardInputToStandardOutput and run on
all non-mobile platforms (not just AnyUnix); simplify via RemoteInvokeOptions.StartInfo
- Simplify SeekableStdoutRedirection test similarly; remove boilerplate try/catch
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/67a83dee-25ae-47d1-ae0f-b4aa1f18265f
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 14, 2026 06:53

CopilotAI commented Apr 14, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please address my feedback

Done in adb2b69. All review feedback addressed:

  • Removed _useFileStreamForIo and extra comments; FileStream is always used for all I/O (handles both seekable and non-seekable correctly)
  • Write() in UnixConsoleStream now calls WriteFromConsoleStream(_fileStream, buffer)
  • WriteFromConsoleStream in both ConsolePal.Unix.cs and ConsolePal.Wasi.cs updated to accept FileStream and call fs.Write(buffer)
  • Tests renamed/simplified and now run on all non-mobile platforms

@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

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
- Fix XML comment in ConsolePal.Wasi.cs Write(FileStream): fd → fs
- Remove _handle field from UnixConsoleStream; FileStream owns handle lifetime
- Remove Flush() override from UnixConsoleStream (base is a nop; bufferSize:0)
- Remove redundant [PlatformSpecific] from two new tests (RemoteExecutor handles it)
- Dispose stdoutHandle before WaitForExit so File.ReadAllText can open the file
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/ba3bd32e-023a-4160-bf27-f0ae05027d8d
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@adamsitnik

Copy link
Copy Markdown
Member

@jozkee@jkotas@stephentoub I would appreciate your review, as I would like to start a longer leave knowing that I leave no known bugs opened.

For context please refer to #126843

This PR is more or less a revert + tests that are going to ensure we are not going to introduce this bug again.

@adamsitnik
adamsitnik enabled auto-merge (squash) April 19, 2026 20:23

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 reverts recent System.Console Unix/WASI I/O changes that used RandomAccess.Read/Write back to the prior Interop.Sys.Read/Write implementation, and adds regression tests for redirected stdin/stdout to seekable files (to prevent hangs/incorrect output).

Changes:

  • Restore Interop.Sys.Read / Interop.Sys.Write-based console stream I/O on Unix and WASI (including the write loop with EPIPE/EAGAIN handling).
  • Add/enable regression tests covering seekable stdin and seekable stdout redirection scenarios.
  • Restore needed interop source inclusions in System.Console.csproj and include ConsoleHandles.cs in the test project.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
src/libraries/System.Console/tests/System.Console.Tests.csprojIncludes ConsoleHandles.cs in the test build.
src/libraries/System.Console/tests/ConsoleHandles.csAdds regression tests for seekable stdin/stdout redirection.
src/libraries/System.Console/src/System/ConsolePal.Wasi.csRestores Interop.Sys.Read/Write + write-loop behavior for WASI.
src/libraries/System.Console/src/System/ConsolePal.Unix.csRestores Interop.Sys.Read/Write + write-loop behavior and cursor-cache updates.
src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csSwitches console stream reads back to ConsolePal.Read (Interop-based).
src/libraries/System.Console/src/System.Console.csprojRe-adds interop source files (Poll/Read/Write) for Unix/WASI builds.

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
auto-merge was automatically disabled April 19, 2026 20:44

Head branch was pushed to by a user without write access

CopilotAI requested a review from adamsitnikApril 19, 2026 20:45
CopilotAI requested review from Copilot and removed request for CopilotApril 19, 2026 20:50
@adamsitnik
adamsitnik merged commit afd1456 into mainApr 20, 2026
91 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-unix-console-stream-bug branch April 20, 2026 05:57
@adamsitnik

Copy link
Copy Markdown
Member

/backport to release/11.0-preview4

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview4 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@adamsitnik backporting to release/11.0-preview4 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchCreating an empty commit: Initial planApplying: Fix UnixConsoleStream to handle seekable files correctlyUsing index info to reconstruct a base tree...M	src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csM	src/libraries/System.Console/tests/ConsoleHandles.csM	src/libraries/System.Console/tests/System.Console.Tests.csprojFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csCONFLICT (content): Merge conflict in src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csAuto-merging src/libraries/System.Console/tests/ConsoleHandles.csCONFLICT (content): Merge conflict in src/libraries/System.Console/tests/ConsoleHandles.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0002 Fix UnixConsoleStream to handle seekable files correctlyError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@adamsitnik

Copy link
Copy Markdown
Member

I am stupid, it was merged before P4 snap so it's already there...

@adamsitnikadamsitnik changed the title Add tests for UnixConsoleStream when stdin/stdout is redirected to a seekable fileFix UnixConsoleStream regression when stdin/stdout is redirected to a seekable fileMay 5, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug in UnixConsoleStream when working with seekable files

4 participants

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

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file - #126844

Merged
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug
Apr 20, 2026
Merged

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file#126844
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug

Conversation

CopilotAI commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Reverts all System.Console source changes from PR #125512 (which introduced RandomAccess.Read/Write based I/O) back to the original Interop.Sys.Read/Write implementation. The FileStream-based approach will be revisited separately.

Adds regression tests that verify Console.OpenStandardInput().CopyTo() and Console.OpenStandardOutput().Write() work correctly when stdin/stdout is redirected to a seekable file.

Description

  • Reverted ConsolePal.Unix.ConsoleStream.cs to use ConsolePal.Read() with Interop.Sys.Read
  • Reverted ConsolePal.Unix.cs to use Interop.Sys.Write with the full write loop (EPIPE, EAGAIN handling) and pointer-based UpdatedCachedCursorPosition
  • Reverted ConsolePal.Wasi.cs to use Interop.Sys.Read/Write directly
  • Restored Interop.Poll.cs, Interop.Read.cs, Interop.Write.cs references in System.Console.csproj for both WASI and Unix targets
  • Restored PR Support the FORCE_COLOR emerging standard in ConsoleUtils.EmitAnsiColorCodes #124492's FORCE_COLOR comment in ConsolePal.Unix.cs that was accidentally reverted along with PR Relax RandomAccess type requirements: make Read/Write methods work with non-seekable files #125512 changes
  • Added ConsoleHandles.cs to System.Console.Tests.csproj (was previously missing)
  • Added CanCopyStandardInputToStandardOutput test — verifies reading from seekable stdin via CopyTo
  • Added UnixConsoleStream_SeekableStdoutRedirection_WritesAllContent test — verifies writing to seekable stdout using two separate Write calls to ensure content is concatenated (not overwritten from offset 0), which properly covers the offset-based write regression

CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 17:27
CopilotAI linked an issue Apr 13, 2026 that may be closed by this pull request
@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.

RandomAccess.Read/Write use pread/pwrite syscalls which always operate at
a specified fileOffset. Passing fileOffset:0 for seekable files (e.g.,
regular files redirected as stdin/stdout) caused reads/writes to always
operate at position 0, resulting in infinite loops or incorrect output.
The fix creates a FileStream (with bufferSize:0) wrapping the handle when
the handle is seekable. FileStream uses OSFileStreamStrategy which tracks
the file position and advances it after each read/write, ensuring correct
sequential behavior for seekable files.
For non-seekable files (pipes, terminals), the existing RandomAccess-based
path is used, preserving cursor position tracking for terminals.
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:15
…g duplication
- Replace 'float for GC' FileStream approach with explicit _useFileStreamForIo bool field;
FileStream is always held and disposed deterministically
- Fix string duplication in stdout test by passing outputContent as RemoteExecutor arg
- Add try/catch around File.Delete in finally blocks
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:17
CopilotAI changed the title [WIP] Fix bug in UnixConsoleStream when working with seekable filesFix UnixConsoleStream when stdin/stdout is redirected to a seekable fileApr 13, 2026
CopilotAI requested a review from adamsitnikApril 13, 2026 18:20

@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 please address my feedback

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
…onsoleStream, simplify tests
- Remove _useFileStreamForIo field and extra comments; always use FileStream for I/O
- Change Write() in UnixConsoleStream to call WriteFromConsoleStream(_fileStream, buffer)
- Update WriteFromConsoleStream in ConsolePal.Unix.cs and ConsolePal.Wasi.cs to accept
FileStream instead of SafeFileHandle; use fs.Write(buffer) which handles both seekable
and non-seekable files correctly
- Rename SeekableStdinRedirection test to CanCopyStandardInputToStandardOutput and run on
all non-mobile platforms (not just AnyUnix); simplify via RemoteInvokeOptions.StartInfo
- Simplify SeekableStdoutRedirection test similarly; remove boilerplate try/catch
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/67a83dee-25ae-47d1-ae0f-b4aa1f18265f
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 14, 2026 06:53

CopilotAI commented Apr 14, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please address my feedback

Done in adb2b69. All review feedback addressed:

  • Removed _useFileStreamForIo and extra comments; FileStream is always used for all I/O (handles both seekable and non-seekable correctly)
  • Write() in UnixConsoleStream now calls WriteFromConsoleStream(_fileStream, buffer)
  • WriteFromConsoleStream in both ConsolePal.Unix.cs and ConsolePal.Wasi.cs updated to accept FileStream and call fs.Write(buffer)
  • Tests renamed/simplified and now run on all non-mobile platforms

@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

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
- Fix XML comment in ConsolePal.Wasi.cs Write(FileStream): fd → fs
- Remove _handle field from UnixConsoleStream; FileStream owns handle lifetime
- Remove Flush() override from UnixConsoleStream (base is a nop; bufferSize:0)
- Remove redundant [PlatformSpecific] from two new tests (RemoteExecutor handles it)
- Dispose stdoutHandle before WaitForExit so File.ReadAllText can open the file
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/ba3bd32e-023a-4160-bf27-f0ae05027d8d
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@adamsitnik

Copy link
Copy Markdown
Member

@jozkee@jkotas@stephentoub I would appreciate your review, as I would like to start a longer leave knowing that I leave no known bugs opened.

For context please refer to #126843

This PR is more or less a revert + tests that are going to ensure we are not going to introduce this bug again.

@adamsitnik
adamsitnik enabled auto-merge (squash) April 19, 2026 20:23

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 reverts recent System.Console Unix/WASI I/O changes that used RandomAccess.Read/Write back to the prior Interop.Sys.Read/Write implementation, and adds regression tests for redirected stdin/stdout to seekable files (to prevent hangs/incorrect output).

Changes:

  • Restore Interop.Sys.Read / Interop.Sys.Write-based console stream I/O on Unix and WASI (including the write loop with EPIPE/EAGAIN handling).
  • Add/enable regression tests covering seekable stdin and seekable stdout redirection scenarios.
  • Restore needed interop source inclusions in System.Console.csproj and include ConsoleHandles.cs in the test project.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
src/libraries/System.Console/tests/System.Console.Tests.csprojIncludes ConsoleHandles.cs in the test build.
src/libraries/System.Console/tests/ConsoleHandles.csAdds regression tests for seekable stdin/stdout redirection.
src/libraries/System.Console/src/System/ConsolePal.Wasi.csRestores Interop.Sys.Read/Write + write-loop behavior for WASI.
src/libraries/System.Console/src/System/ConsolePal.Unix.csRestores Interop.Sys.Read/Write + write-loop behavior and cursor-cache updates.
src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csSwitches console stream reads back to ConsolePal.Read (Interop-based).
src/libraries/System.Console/src/System.Console.csprojRe-adds interop source files (Poll/Read/Write) for Unix/WASI builds.

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
auto-merge was automatically disabled April 19, 2026 20:44

Head branch was pushed to by a user without write access

CopilotAI requested a review from adamsitnikApril 19, 2026 20:45
CopilotAI requested review from Copilot and removed request for CopilotApril 19, 2026 20:50
@adamsitnik
adamsitnik merged commit afd1456 into mainApr 20, 2026
91 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-unix-console-stream-bug branch April 20, 2026 05:57
@adamsitnik

Copy link
Copy Markdown
Member

/backport to release/11.0-preview4

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview4 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@adamsitnik backporting to release/11.0-preview4 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchCreating an empty commit: Initial planApplying: Fix UnixConsoleStream to handle seekable files correctlyUsing index info to reconstruct a base tree...M	src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csM	src/libraries/System.Console/tests/ConsoleHandles.csM	src/libraries/System.Console/tests/System.Console.Tests.csprojFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csCONFLICT (content): Merge conflict in src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csAuto-merging src/libraries/System.Console/tests/ConsoleHandles.csCONFLICT (content): Merge conflict in src/libraries/System.Console/tests/ConsoleHandles.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0002 Fix UnixConsoleStream to handle seekable files correctlyError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@adamsitnik

Copy link
Copy Markdown
Member

I am stupid, it was merged before P4 snap so it's already there...

@adamsitnikadamsitnik changed the title Add tests for UnixConsoleStream when stdin/stdout is redirected to a seekable fileFix UnixConsoleStream regression when stdin/stdout is redirected to a seekable fileMay 5, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug in UnixConsoleStream when working with seekable files

4 participants

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

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file - #126844

Merged
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug
Apr 20, 2026
Merged

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file#126844
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug

Conversation

CopilotAI commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Reverts all System.Console source changes from PR #125512 (which introduced RandomAccess.Read/Write based I/O) back to the original Interop.Sys.Read/Write implementation. The FileStream-based approach will be revisited separately.

Adds regression tests that verify Console.OpenStandardInput().CopyTo() and Console.OpenStandardOutput().Write() work correctly when stdin/stdout is redirected to a seekable file.

Description

  • Reverted ConsolePal.Unix.ConsoleStream.cs to use ConsolePal.Read() with Interop.Sys.Read
  • Reverted ConsolePal.Unix.cs to use Interop.Sys.Write with the full write loop (EPIPE, EAGAIN handling) and pointer-based UpdatedCachedCursorPosition
  • Reverted ConsolePal.Wasi.cs to use Interop.Sys.Read/Write directly
  • Restored Interop.Poll.cs, Interop.Read.cs, Interop.Write.cs references in System.Console.csproj for both WASI and Unix targets
  • Restored PR Support the FORCE_COLOR emerging standard in ConsoleUtils.EmitAnsiColorCodes #124492's FORCE_COLOR comment in ConsolePal.Unix.cs that was accidentally reverted along with PR Relax RandomAccess type requirements: make Read/Write methods work with non-seekable files #125512 changes
  • Added ConsoleHandles.cs to System.Console.Tests.csproj (was previously missing)
  • Added CanCopyStandardInputToStandardOutput test — verifies reading from seekable stdin via CopyTo
  • Added UnixConsoleStream_SeekableStdoutRedirection_WritesAllContent test — verifies writing to seekable stdout using two separate Write calls to ensure content is concatenated (not overwritten from offset 0), which properly covers the offset-based write regression

CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 17:27
CopilotAI linked an issue Apr 13, 2026 that may be closed by this pull request
@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.

RandomAccess.Read/Write use pread/pwrite syscalls which always operate at
a specified fileOffset. Passing fileOffset:0 for seekable files (e.g.,
regular files redirected as stdin/stdout) caused reads/writes to always
operate at position 0, resulting in infinite loops or incorrect output.
The fix creates a FileStream (with bufferSize:0) wrapping the handle when
the handle is seekable. FileStream uses OSFileStreamStrategy which tracks
the file position and advances it after each read/write, ensuring correct
sequential behavior for seekable files.
For non-seekable files (pipes, terminals), the existing RandomAccess-based
path is used, preserving cursor position tracking for terminals.
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:15
…g duplication
- Replace 'float for GC' FileStream approach with explicit _useFileStreamForIo bool field;
FileStream is always held and disposed deterministically
- Fix string duplication in stdout test by passing outputContent as RemoteExecutor arg
- Add try/catch around File.Delete in finally blocks
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:17
CopilotAI changed the title [WIP] Fix bug in UnixConsoleStream when working with seekable filesFix UnixConsoleStream when stdin/stdout is redirected to a seekable fileApr 13, 2026
CopilotAI requested a review from adamsitnikApril 13, 2026 18:20

@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 please address my feedback

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
…onsoleStream, simplify tests
- Remove _useFileStreamForIo field and extra comments; always use FileStream for I/O
- Change Write() in UnixConsoleStream to call WriteFromConsoleStream(_fileStream, buffer)
- Update WriteFromConsoleStream in ConsolePal.Unix.cs and ConsolePal.Wasi.cs to accept
FileStream instead of SafeFileHandle; use fs.Write(buffer) which handles both seekable
and non-seekable files correctly
- Rename SeekableStdinRedirection test to CanCopyStandardInputToStandardOutput and run on
all non-mobile platforms (not just AnyUnix); simplify via RemoteInvokeOptions.StartInfo
- Simplify SeekableStdoutRedirection test similarly; remove boilerplate try/catch
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/67a83dee-25ae-47d1-ae0f-b4aa1f18265f
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 14, 2026 06:53

CopilotAI commented Apr 14, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please address my feedback

Done in adb2b69. All review feedback addressed:

  • Removed _useFileStreamForIo and extra comments; FileStream is always used for all I/O (handles both seekable and non-seekable correctly)
  • Write() in UnixConsoleStream now calls WriteFromConsoleStream(_fileStream, buffer)
  • WriteFromConsoleStream in both ConsolePal.Unix.cs and ConsolePal.Wasi.cs updated to accept FileStream and call fs.Write(buffer)
  • Tests renamed/simplified and now run on all non-mobile platforms

@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

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
- Fix XML comment in ConsolePal.Wasi.cs Write(FileStream): fd → fs
- Remove _handle field from UnixConsoleStream; FileStream owns handle lifetime
- Remove Flush() override from UnixConsoleStream (base is a nop; bufferSize:0)
- Remove redundant [PlatformSpecific] from two new tests (RemoteExecutor handles it)
- Dispose stdoutHandle before WaitForExit so File.ReadAllText can open the file
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/ba3bd32e-023a-4160-bf27-f0ae05027d8d
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@adamsitnik

Copy link
Copy Markdown
Member

@jozkee@jkotas@stephentoub I would appreciate your review, as I would like to start a longer leave knowing that I leave no known bugs opened.

For context please refer to #126843

This PR is more or less a revert + tests that are going to ensure we are not going to introduce this bug again.

@adamsitnik
adamsitnik enabled auto-merge (squash) April 19, 2026 20:23

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 reverts recent System.Console Unix/WASI I/O changes that used RandomAccess.Read/Write back to the prior Interop.Sys.Read/Write implementation, and adds regression tests for redirected stdin/stdout to seekable files (to prevent hangs/incorrect output).

Changes:

  • Restore Interop.Sys.Read / Interop.Sys.Write-based console stream I/O on Unix and WASI (including the write loop with EPIPE/EAGAIN handling).
  • Add/enable regression tests covering seekable stdin and seekable stdout redirection scenarios.
  • Restore needed interop source inclusions in System.Console.csproj and include ConsoleHandles.cs in the test project.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
src/libraries/System.Console/tests/System.Console.Tests.csprojIncludes ConsoleHandles.cs in the test build.
src/libraries/System.Console/tests/ConsoleHandles.csAdds regression tests for seekable stdin/stdout redirection.
src/libraries/System.Console/src/System/ConsolePal.Wasi.csRestores Interop.Sys.Read/Write + write-loop behavior for WASI.
src/libraries/System.Console/src/System/ConsolePal.Unix.csRestores Interop.Sys.Read/Write + write-loop behavior and cursor-cache updates.
src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csSwitches console stream reads back to ConsolePal.Read (Interop-based).
src/libraries/System.Console/src/System.Console.csprojRe-adds interop source files (Poll/Read/Write) for Unix/WASI builds.

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
auto-merge was automatically disabled April 19, 2026 20:44

Head branch was pushed to by a user without write access

CopilotAI requested a review from adamsitnikApril 19, 2026 20:45
CopilotAI requested review from Copilot and removed request for CopilotApril 19, 2026 20:50
@adamsitnik
adamsitnik merged commit afd1456 into mainApr 20, 2026
91 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-unix-console-stream-bug branch April 20, 2026 05:57
@adamsitnik

Copy link
Copy Markdown
Member

/backport to release/11.0-preview4

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview4 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@adamsitnik backporting to release/11.0-preview4 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchCreating an empty commit: Initial planApplying: Fix UnixConsoleStream to handle seekable files correctlyUsing index info to reconstruct a base tree...M	src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csM	src/libraries/System.Console/tests/ConsoleHandles.csM	src/libraries/System.Console/tests/System.Console.Tests.csprojFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csCONFLICT (content): Merge conflict in src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csAuto-merging src/libraries/System.Console/tests/ConsoleHandles.csCONFLICT (content): Merge conflict in src/libraries/System.Console/tests/ConsoleHandles.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0002 Fix UnixConsoleStream to handle seekable files correctlyError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@adamsitnik

Copy link
Copy Markdown
Member

I am stupid, it was merged before P4 snap so it's already there...

@adamsitnikadamsitnik changed the title Add tests for UnixConsoleStream when stdin/stdout is redirected to a seekable fileFix UnixConsoleStream regression when stdin/stdout is redirected to a seekable fileMay 5, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug in UnixConsoleStream when working with seekable files

4 participants

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

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file - #126844

Merged
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug
Apr 20, 2026
Merged

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file#126844
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug

Conversation

CopilotAI commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Reverts all System.Console source changes from PR #125512 (which introduced RandomAccess.Read/Write based I/O) back to the original Interop.Sys.Read/Write implementation. The FileStream-based approach will be revisited separately.

Adds regression tests that verify Console.OpenStandardInput().CopyTo() and Console.OpenStandardOutput().Write() work correctly when stdin/stdout is redirected to a seekable file.

Description

  • Reverted ConsolePal.Unix.ConsoleStream.cs to use ConsolePal.Read() with Interop.Sys.Read
  • Reverted ConsolePal.Unix.cs to use Interop.Sys.Write with the full write loop (EPIPE, EAGAIN handling) and pointer-based UpdatedCachedCursorPosition
  • Reverted ConsolePal.Wasi.cs to use Interop.Sys.Read/Write directly
  • Restored Interop.Poll.cs, Interop.Read.cs, Interop.Write.cs references in System.Console.csproj for both WASI and Unix targets
  • Restored PR Support the FORCE_COLOR emerging standard in ConsoleUtils.EmitAnsiColorCodes #124492's FORCE_COLOR comment in ConsolePal.Unix.cs that was accidentally reverted along with PR Relax RandomAccess type requirements: make Read/Write methods work with non-seekable files #125512 changes
  • Added ConsoleHandles.cs to System.Console.Tests.csproj (was previously missing)
  • Added CanCopyStandardInputToStandardOutput test — verifies reading from seekable stdin via CopyTo
  • Added UnixConsoleStream_SeekableStdoutRedirection_WritesAllContent test — verifies writing to seekable stdout using two separate Write calls to ensure content is concatenated (not overwritten from offset 0), which properly covers the offset-based write regression

CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 17:27
CopilotAI linked an issue Apr 13, 2026 that may be closed by this pull request
@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.

RandomAccess.Read/Write use pread/pwrite syscalls which always operate at
a specified fileOffset. Passing fileOffset:0 for seekable files (e.g.,
regular files redirected as stdin/stdout) caused reads/writes to always
operate at position 0, resulting in infinite loops or incorrect output.
The fix creates a FileStream (with bufferSize:0) wrapping the handle when
the handle is seekable. FileStream uses OSFileStreamStrategy which tracks
the file position and advances it after each read/write, ensuring correct
sequential behavior for seekable files.
For non-seekable files (pipes, terminals), the existing RandomAccess-based
path is used, preserving cursor position tracking for terminals.
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:15
…g duplication
- Replace 'float for GC' FileStream approach with explicit _useFileStreamForIo bool field;
FileStream is always held and disposed deterministically
- Fix string duplication in stdout test by passing outputContent as RemoteExecutor arg
- Add try/catch around File.Delete in finally blocks
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:17
CopilotAI changed the title [WIP] Fix bug in UnixConsoleStream when working with seekable filesFix UnixConsoleStream when stdin/stdout is redirected to a seekable fileApr 13, 2026
CopilotAI requested a review from adamsitnikApril 13, 2026 18:20

@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 please address my feedback

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
…onsoleStream, simplify tests
- Remove _useFileStreamForIo field and extra comments; always use FileStream for I/O
- Change Write() in UnixConsoleStream to call WriteFromConsoleStream(_fileStream, buffer)
- Update WriteFromConsoleStream in ConsolePal.Unix.cs and ConsolePal.Wasi.cs to accept
FileStream instead of SafeFileHandle; use fs.Write(buffer) which handles both seekable
and non-seekable files correctly
- Rename SeekableStdinRedirection test to CanCopyStandardInputToStandardOutput and run on
all non-mobile platforms (not just AnyUnix); simplify via RemoteInvokeOptions.StartInfo
- Simplify SeekableStdoutRedirection test similarly; remove boilerplate try/catch
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/67a83dee-25ae-47d1-ae0f-b4aa1f18265f
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 14, 2026 06:53

CopilotAI commented Apr 14, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please address my feedback

Done in adb2b69. All review feedback addressed:

  • Removed _useFileStreamForIo and extra comments; FileStream is always used for all I/O (handles both seekable and non-seekable correctly)
  • Write() in UnixConsoleStream now calls WriteFromConsoleStream(_fileStream, buffer)
  • WriteFromConsoleStream in both ConsolePal.Unix.cs and ConsolePal.Wasi.cs updated to accept FileStream and call fs.Write(buffer)
  • Tests renamed/simplified and now run on all non-mobile platforms

@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

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
- Fix XML comment in ConsolePal.Wasi.cs Write(FileStream): fd → fs
- Remove _handle field from UnixConsoleStream; FileStream owns handle lifetime
- Remove Flush() override from UnixConsoleStream (base is a nop; bufferSize:0)
- Remove redundant [PlatformSpecific] from two new tests (RemoteExecutor handles it)
- Dispose stdoutHandle before WaitForExit so File.ReadAllText can open the file
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/ba3bd32e-023a-4160-bf27-f0ae05027d8d
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@adamsitnik

Copy link
Copy Markdown
Member

@jozkee@jkotas@stephentoub I would appreciate your review, as I would like to start a longer leave knowing that I leave no known bugs opened.

For context please refer to #126843

This PR is more or less a revert + tests that are going to ensure we are not going to introduce this bug again.

@adamsitnik
adamsitnik enabled auto-merge (squash) April 19, 2026 20:23

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 reverts recent System.Console Unix/WASI I/O changes that used RandomAccess.Read/Write back to the prior Interop.Sys.Read/Write implementation, and adds regression tests for redirected stdin/stdout to seekable files (to prevent hangs/incorrect output).

Changes:

  • Restore Interop.Sys.Read / Interop.Sys.Write-based console stream I/O on Unix and WASI (including the write loop with EPIPE/EAGAIN handling).
  • Add/enable regression tests covering seekable stdin and seekable stdout redirection scenarios.
  • Restore needed interop source inclusions in System.Console.csproj and include ConsoleHandles.cs in the test project.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
src/libraries/System.Console/tests/System.Console.Tests.csprojIncludes ConsoleHandles.cs in the test build.
src/libraries/System.Console/tests/ConsoleHandles.csAdds regression tests for seekable stdin/stdout redirection.
src/libraries/System.Console/src/System/ConsolePal.Wasi.csRestores Interop.Sys.Read/Write + write-loop behavior for WASI.
src/libraries/System.Console/src/System/ConsolePal.Unix.csRestores Interop.Sys.Read/Write + write-loop behavior and cursor-cache updates.
src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csSwitches console stream reads back to ConsolePal.Read (Interop-based).
src/libraries/System.Console/src/System.Console.csprojRe-adds interop source files (Poll/Read/Write) for Unix/WASI builds.

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
auto-merge was automatically disabled April 19, 2026 20:44

Head branch was pushed to by a user without write access

CopilotAI requested a review from adamsitnikApril 19, 2026 20:45
CopilotAI requested review from Copilot and removed request for CopilotApril 19, 2026 20:50
@adamsitnik
adamsitnik merged commit afd1456 into mainApr 20, 2026
91 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-unix-console-stream-bug branch April 20, 2026 05:57
@adamsitnik

Copy link
Copy Markdown
Member

/backport to release/11.0-preview4

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview4 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@adamsitnik backporting to release/11.0-preview4 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchCreating an empty commit: Initial planApplying: Fix UnixConsoleStream to handle seekable files correctlyUsing index info to reconstruct a base tree...M	src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csM	src/libraries/System.Console/tests/ConsoleHandles.csM	src/libraries/System.Console/tests/System.Console.Tests.csprojFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csCONFLICT (content): Merge conflict in src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csAuto-merging src/libraries/System.Console/tests/ConsoleHandles.csCONFLICT (content): Merge conflict in src/libraries/System.Console/tests/ConsoleHandles.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0002 Fix UnixConsoleStream to handle seekable files correctlyError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@adamsitnik

Copy link
Copy Markdown
Member

I am stupid, it was merged before P4 snap so it's already there...

@adamsitnikadamsitnik changed the title Add tests for UnixConsoleStream when stdin/stdout is redirected to a seekable fileFix UnixConsoleStream regression when stdin/stdout is redirected to a seekable fileMay 5, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug in UnixConsoleStream when working with seekable files

4 participants

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

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file - #126844

Merged
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug
Apr 20, 2026
Merged

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file#126844
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug

Conversation

CopilotAI commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Reverts all System.Console source changes from PR #125512 (which introduced RandomAccess.Read/Write based I/O) back to the original Interop.Sys.Read/Write implementation. The FileStream-based approach will be revisited separately.

Adds regression tests that verify Console.OpenStandardInput().CopyTo() and Console.OpenStandardOutput().Write() work correctly when stdin/stdout is redirected to a seekable file.

Description

  • Reverted ConsolePal.Unix.ConsoleStream.cs to use ConsolePal.Read() with Interop.Sys.Read
  • Reverted ConsolePal.Unix.cs to use Interop.Sys.Write with the full write loop (EPIPE, EAGAIN handling) and pointer-based UpdatedCachedCursorPosition
  • Reverted ConsolePal.Wasi.cs to use Interop.Sys.Read/Write directly
  • Restored Interop.Poll.cs, Interop.Read.cs, Interop.Write.cs references in System.Console.csproj for both WASI and Unix targets
  • Restored PR Support the FORCE_COLOR emerging standard in ConsoleUtils.EmitAnsiColorCodes #124492's FORCE_COLOR comment in ConsolePal.Unix.cs that was accidentally reverted along with PR Relax RandomAccess type requirements: make Read/Write methods work with non-seekable files #125512 changes
  • Added ConsoleHandles.cs to System.Console.Tests.csproj (was previously missing)
  • Added CanCopyStandardInputToStandardOutput test — verifies reading from seekable stdin via CopyTo
  • Added UnixConsoleStream_SeekableStdoutRedirection_WritesAllContent test — verifies writing to seekable stdout using two separate Write calls to ensure content is concatenated (not overwritten from offset 0), which properly covers the offset-based write regression

CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 17:27
CopilotAI linked an issue Apr 13, 2026 that may be closed by this pull request
@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.

RandomAccess.Read/Write use pread/pwrite syscalls which always operate at
a specified fileOffset. Passing fileOffset:0 for seekable files (e.g.,
regular files redirected as stdin/stdout) caused reads/writes to always
operate at position 0, resulting in infinite loops or incorrect output.
The fix creates a FileStream (with bufferSize:0) wrapping the handle when
the handle is seekable. FileStream uses OSFileStreamStrategy which tracks
the file position and advances it after each read/write, ensuring correct
sequential behavior for seekable files.
For non-seekable files (pipes, terminals), the existing RandomAccess-based
path is used, preserving cursor position tracking for terminals.
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:15
…g duplication
- Replace 'float for GC' FileStream approach with explicit _useFileStreamForIo bool field;
FileStream is always held and disposed deterministically
- Fix string duplication in stdout test by passing outputContent as RemoteExecutor arg
- Add try/catch around File.Delete in finally blocks
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:17
CopilotAI changed the title [WIP] Fix bug in UnixConsoleStream when working with seekable filesFix UnixConsoleStream when stdin/stdout is redirected to a seekable fileApr 13, 2026
CopilotAI requested a review from adamsitnikApril 13, 2026 18:20

@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 please address my feedback

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
…onsoleStream, simplify tests
- Remove _useFileStreamForIo field and extra comments; always use FileStream for I/O
- Change Write() in UnixConsoleStream to call WriteFromConsoleStream(_fileStream, buffer)
- Update WriteFromConsoleStream in ConsolePal.Unix.cs and ConsolePal.Wasi.cs to accept
FileStream instead of SafeFileHandle; use fs.Write(buffer) which handles both seekable
and non-seekable files correctly
- Rename SeekableStdinRedirection test to CanCopyStandardInputToStandardOutput and run on
all non-mobile platforms (not just AnyUnix); simplify via RemoteInvokeOptions.StartInfo
- Simplify SeekableStdoutRedirection test similarly; remove boilerplate try/catch
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/67a83dee-25ae-47d1-ae0f-b4aa1f18265f
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 14, 2026 06:53

CopilotAI commented Apr 14, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please address my feedback

Done in adb2b69. All review feedback addressed:

  • Removed _useFileStreamForIo and extra comments; FileStream is always used for all I/O (handles both seekable and non-seekable correctly)
  • Write() in UnixConsoleStream now calls WriteFromConsoleStream(_fileStream, buffer)
  • WriteFromConsoleStream in both ConsolePal.Unix.cs and ConsolePal.Wasi.cs updated to accept FileStream and call fs.Write(buffer)
  • Tests renamed/simplified and now run on all non-mobile platforms

@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

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
- Fix XML comment in ConsolePal.Wasi.cs Write(FileStream): fd → fs
- Remove _handle field from UnixConsoleStream; FileStream owns handle lifetime
- Remove Flush() override from UnixConsoleStream (base is a nop; bufferSize:0)
- Remove redundant [PlatformSpecific] from two new tests (RemoteExecutor handles it)
- Dispose stdoutHandle before WaitForExit so File.ReadAllText can open the file
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/ba3bd32e-023a-4160-bf27-f0ae05027d8d
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@adamsitnik

Copy link
Copy Markdown
Member

@jozkee@jkotas@stephentoub I would appreciate your review, as I would like to start a longer leave knowing that I leave no known bugs opened.

For context please refer to #126843

This PR is more or less a revert + tests that are going to ensure we are not going to introduce this bug again.

@adamsitnik
adamsitnik enabled auto-merge (squash) April 19, 2026 20:23

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 reverts recent System.Console Unix/WASI I/O changes that used RandomAccess.Read/Write back to the prior Interop.Sys.Read/Write implementation, and adds regression tests for redirected stdin/stdout to seekable files (to prevent hangs/incorrect output).

Changes:

  • Restore Interop.Sys.Read / Interop.Sys.Write-based console stream I/O on Unix and WASI (including the write loop with EPIPE/EAGAIN handling).
  • Add/enable regression tests covering seekable stdin and seekable stdout redirection scenarios.
  • Restore needed interop source inclusions in System.Console.csproj and include ConsoleHandles.cs in the test project.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
src/libraries/System.Console/tests/System.Console.Tests.csprojIncludes ConsoleHandles.cs in the test build.
src/libraries/System.Console/tests/ConsoleHandles.csAdds regression tests for seekable stdin/stdout redirection.
src/libraries/System.Console/src/System/ConsolePal.Wasi.csRestores Interop.Sys.Read/Write + write-loop behavior for WASI.
src/libraries/System.Console/src/System/ConsolePal.Unix.csRestores Interop.Sys.Read/Write + write-loop behavior and cursor-cache updates.
src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csSwitches console stream reads back to ConsolePal.Read (Interop-based).
src/libraries/System.Console/src/System.Console.csprojRe-adds interop source files (Poll/Read/Write) for Unix/WASI builds.

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
auto-merge was automatically disabled April 19, 2026 20:44

Head branch was pushed to by a user without write access

CopilotAI requested a review from adamsitnikApril 19, 2026 20:45
CopilotAI requested review from Copilot and removed request for CopilotApril 19, 2026 20:50
@adamsitnik
adamsitnik merged commit afd1456 into mainApr 20, 2026
91 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-unix-console-stream-bug branch April 20, 2026 05:57
@adamsitnik

Copy link
Copy Markdown
Member

/backport to release/11.0-preview4

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview4 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@adamsitnik backporting to release/11.0-preview4 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchCreating an empty commit: Initial planApplying: Fix UnixConsoleStream to handle seekable files correctlyUsing index info to reconstruct a base tree...M	src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csM	src/libraries/System.Console/tests/ConsoleHandles.csM	src/libraries/System.Console/tests/System.Console.Tests.csprojFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csCONFLICT (content): Merge conflict in src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csAuto-merging src/libraries/System.Console/tests/ConsoleHandles.csCONFLICT (content): Merge conflict in src/libraries/System.Console/tests/ConsoleHandles.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0002 Fix UnixConsoleStream to handle seekable files correctlyError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@adamsitnik

Copy link
Copy Markdown
Member

I am stupid, it was merged before P4 snap so it's already there...

@adamsitnikadamsitnik changed the title Add tests for UnixConsoleStream when stdin/stdout is redirected to a seekable fileFix UnixConsoleStream regression when stdin/stdout is redirected to a seekable fileMay 5, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug in UnixConsoleStream when working with seekable files

4 participants

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

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file - #126844

Merged
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug
Apr 20, 2026
Merged

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file#126844
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug

Conversation

CopilotAI commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Reverts all System.Console source changes from PR #125512 (which introduced RandomAccess.Read/Write based I/O) back to the original Interop.Sys.Read/Write implementation. The FileStream-based approach will be revisited separately.

Adds regression tests that verify Console.OpenStandardInput().CopyTo() and Console.OpenStandardOutput().Write() work correctly when stdin/stdout is redirected to a seekable file.

Description

  • Reverted ConsolePal.Unix.ConsoleStream.cs to use ConsolePal.Read() with Interop.Sys.Read
  • Reverted ConsolePal.Unix.cs to use Interop.Sys.Write with the full write loop (EPIPE, EAGAIN handling) and pointer-based UpdatedCachedCursorPosition
  • Reverted ConsolePal.Wasi.cs to use Interop.Sys.Read/Write directly
  • Restored Interop.Poll.cs, Interop.Read.cs, Interop.Write.cs references in System.Console.csproj for both WASI and Unix targets
  • Restored PR Support the FORCE_COLOR emerging standard in ConsoleUtils.EmitAnsiColorCodes #124492's FORCE_COLOR comment in ConsolePal.Unix.cs that was accidentally reverted along with PR Relax RandomAccess type requirements: make Read/Write methods work with non-seekable files #125512 changes
  • Added ConsoleHandles.cs to System.Console.Tests.csproj (was previously missing)
  • Added CanCopyStandardInputToStandardOutput test — verifies reading from seekable stdin via CopyTo
  • Added UnixConsoleStream_SeekableStdoutRedirection_WritesAllContent test — verifies writing to seekable stdout using two separate Write calls to ensure content is concatenated (not overwritten from offset 0), which properly covers the offset-based write regression

CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 17:27
CopilotAI linked an issue Apr 13, 2026 that may be closed by this pull request
@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.

RandomAccess.Read/Write use pread/pwrite syscalls which always operate at
a specified fileOffset. Passing fileOffset:0 for seekable files (e.g.,
regular files redirected as stdin/stdout) caused reads/writes to always
operate at position 0, resulting in infinite loops or incorrect output.
The fix creates a FileStream (with bufferSize:0) wrapping the handle when
the handle is seekable. FileStream uses OSFileStreamStrategy which tracks
the file position and advances it after each read/write, ensuring correct
sequential behavior for seekable files.
For non-seekable files (pipes, terminals), the existing RandomAccess-based
path is used, preserving cursor position tracking for terminals.
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:15
…g duplication
- Replace 'float for GC' FileStream approach with explicit _useFileStreamForIo bool field;
FileStream is always held and disposed deterministically
- Fix string duplication in stdout test by passing outputContent as RemoteExecutor arg
- Add try/catch around File.Delete in finally blocks
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:17
CopilotAI changed the title [WIP] Fix bug in UnixConsoleStream when working with seekable filesFix UnixConsoleStream when stdin/stdout is redirected to a seekable fileApr 13, 2026
CopilotAI requested a review from adamsitnikApril 13, 2026 18:20

@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 please address my feedback

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
…onsoleStream, simplify tests
- Remove _useFileStreamForIo field and extra comments; always use FileStream for I/O
- Change Write() in UnixConsoleStream to call WriteFromConsoleStream(_fileStream, buffer)
- Update WriteFromConsoleStream in ConsolePal.Unix.cs and ConsolePal.Wasi.cs to accept
FileStream instead of SafeFileHandle; use fs.Write(buffer) which handles both seekable
and non-seekable files correctly
- Rename SeekableStdinRedirection test to CanCopyStandardInputToStandardOutput and run on
all non-mobile platforms (not just AnyUnix); simplify via RemoteInvokeOptions.StartInfo
- Simplify SeekableStdoutRedirection test similarly; remove boilerplate try/catch
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/67a83dee-25ae-47d1-ae0f-b4aa1f18265f
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 14, 2026 06:53

CopilotAI commented Apr 14, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please address my feedback

Done in adb2b69. All review feedback addressed:

  • Removed _useFileStreamForIo and extra comments; FileStream is always used for all I/O (handles both seekable and non-seekable correctly)
  • Write() in UnixConsoleStream now calls WriteFromConsoleStream(_fileStream, buffer)
  • WriteFromConsoleStream in both ConsolePal.Unix.cs and ConsolePal.Wasi.cs updated to accept FileStream and call fs.Write(buffer)
  • Tests renamed/simplified and now run on all non-mobile platforms

@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

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
- Fix XML comment in ConsolePal.Wasi.cs Write(FileStream): fd → fs
- Remove _handle field from UnixConsoleStream; FileStream owns handle lifetime
- Remove Flush() override from UnixConsoleStream (base is a nop; bufferSize:0)
- Remove redundant [PlatformSpecific] from two new tests (RemoteExecutor handles it)
- Dispose stdoutHandle before WaitForExit so File.ReadAllText can open the file
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/ba3bd32e-023a-4160-bf27-f0ae05027d8d
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@adamsitnik

Copy link
Copy Markdown
Member

@jozkee@jkotas@stephentoub I would appreciate your review, as I would like to start a longer leave knowing that I leave no known bugs opened.

For context please refer to #126843

This PR is more or less a revert + tests that are going to ensure we are not going to introduce this bug again.

@adamsitnik
adamsitnik enabled auto-merge (squash) April 19, 2026 20:23

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 reverts recent System.Console Unix/WASI I/O changes that used RandomAccess.Read/Write back to the prior Interop.Sys.Read/Write implementation, and adds regression tests for redirected stdin/stdout to seekable files (to prevent hangs/incorrect output).

Changes:

  • Restore Interop.Sys.Read / Interop.Sys.Write-based console stream I/O on Unix and WASI (including the write loop with EPIPE/EAGAIN handling).
  • Add/enable regression tests covering seekable stdin and seekable stdout redirection scenarios.
  • Restore needed interop source inclusions in System.Console.csproj and include ConsoleHandles.cs in the test project.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
src/libraries/System.Console/tests/System.Console.Tests.csprojIncludes ConsoleHandles.cs in the test build.
src/libraries/System.Console/tests/ConsoleHandles.csAdds regression tests for seekable stdin/stdout redirection.
src/libraries/System.Console/src/System/ConsolePal.Wasi.csRestores Interop.Sys.Read/Write + write-loop behavior for WASI.
src/libraries/System.Console/src/System/ConsolePal.Unix.csRestores Interop.Sys.Read/Write + write-loop behavior and cursor-cache updates.
src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csSwitches console stream reads back to ConsolePal.Read (Interop-based).
src/libraries/System.Console/src/System.Console.csprojRe-adds interop source files (Poll/Read/Write) for Unix/WASI builds.

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
auto-merge was automatically disabled April 19, 2026 20:44

Head branch was pushed to by a user without write access

CopilotAI requested a review from adamsitnikApril 19, 2026 20:45
CopilotAI requested review from Copilot and removed request for CopilotApril 19, 2026 20:50
@adamsitnik
adamsitnik merged commit afd1456 into mainApr 20, 2026
91 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-unix-console-stream-bug branch April 20, 2026 05:57
@adamsitnik

Copy link
Copy Markdown
Member

/backport to release/11.0-preview4

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview4 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@adamsitnik backporting to release/11.0-preview4 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchCreating an empty commit: Initial planApplying: Fix UnixConsoleStream to handle seekable files correctlyUsing index info to reconstruct a base tree...M	src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csM	src/libraries/System.Console/tests/ConsoleHandles.csM	src/libraries/System.Console/tests/System.Console.Tests.csprojFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csCONFLICT (content): Merge conflict in src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csAuto-merging src/libraries/System.Console/tests/ConsoleHandles.csCONFLICT (content): Merge conflict in src/libraries/System.Console/tests/ConsoleHandles.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0002 Fix UnixConsoleStream to handle seekable files correctlyError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@adamsitnik

Copy link
Copy Markdown
Member

I am stupid, it was merged before P4 snap so it's already there...

@adamsitnikadamsitnik changed the title Add tests for UnixConsoleStream when stdin/stdout is redirected to a seekable fileFix UnixConsoleStream regression when stdin/stdout is redirected to a seekable fileMay 5, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug in UnixConsoleStream when working with seekable files

4 participants

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

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file - #126844

Merged
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug
Apr 20, 2026
Merged

Fix UnixConsoleStream regression when stdin/stdout is redirected to a seekable file#126844
adamsitnik merged 10 commits into
mainfrom
copilot/fix-unix-console-stream-bug

Conversation

CopilotAI commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Reverts all System.Console source changes from PR #125512 (which introduced RandomAccess.Read/Write based I/O) back to the original Interop.Sys.Read/Write implementation. The FileStream-based approach will be revisited separately.

Adds regression tests that verify Console.OpenStandardInput().CopyTo() and Console.OpenStandardOutput().Write() work correctly when stdin/stdout is redirected to a seekable file.

Description

  • Reverted ConsolePal.Unix.ConsoleStream.cs to use ConsolePal.Read() with Interop.Sys.Read
  • Reverted ConsolePal.Unix.cs to use Interop.Sys.Write with the full write loop (EPIPE, EAGAIN handling) and pointer-based UpdatedCachedCursorPosition
  • Reverted ConsolePal.Wasi.cs to use Interop.Sys.Read/Write directly
  • Restored Interop.Poll.cs, Interop.Read.cs, Interop.Write.cs references in System.Console.csproj for both WASI and Unix targets
  • Restored PR Support the FORCE_COLOR emerging standard in ConsoleUtils.EmitAnsiColorCodes #124492's FORCE_COLOR comment in ConsolePal.Unix.cs that was accidentally reverted along with PR Relax RandomAccess type requirements: make Read/Write methods work with non-seekable files #125512 changes
  • Added ConsoleHandles.cs to System.Console.Tests.csproj (was previously missing)
  • Added CanCopyStandardInputToStandardOutput test — verifies reading from seekable stdin via CopyTo
  • Added UnixConsoleStream_SeekableStdoutRedirection_WritesAllContent test — verifies writing to seekable stdout using two separate Write calls to ensure content is concatenated (not overwritten from offset 0), which properly covers the offset-based write regression

CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 17:27
CopilotAI linked an issue Apr 13, 2026 that may be closed by this pull request
@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.

RandomAccess.Read/Write use pread/pwrite syscalls which always operate at
a specified fileOffset. Passing fileOffset:0 for seekable files (e.g.,
regular files redirected as stdin/stdout) caused reads/writes to always
operate at position 0, resulting in infinite loops or incorrect output.
The fix creates a FileStream (with bufferSize:0) wrapping the handle when
the handle is seekable. FileStream uses OSFileStreamStrategy which tracks
the file position and advances it after each read/write, ensuring correct
sequential behavior for seekable files.
For non-seekable files (pipes, terminals), the existing RandomAccess-based
path is used, preserving cursor position tracking for terminals.
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:15
…g duplication
- Replace 'float for GC' FileStream approach with explicit _useFileStreamForIo bool field;
FileStream is always held and disposed deterministically
- Fix string duplication in stdout test by passing outputContent as RemoteExecutor arg
- Add try/catch around File.Delete in finally blocks
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0df60225-7783-4496-abcf-9917387f56e5
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 13, 2026 18:17
CopilotAI changed the title [WIP] Fix bug in UnixConsoleStream when working with seekable filesFix UnixConsoleStream when stdin/stdout is redirected to a seekable fileApr 13, 2026
CopilotAI requested a review from adamsitnikApril 13, 2026 18:20

@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 please address my feedback

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.cs Outdated
…onsoleStream, simplify tests
- Remove _useFileStreamForIo field and extra comments; always use FileStream for I/O
- Change Write() in UnixConsoleStream to call WriteFromConsoleStream(_fileStream, buffer)
- Update WriteFromConsoleStream in ConsolePal.Unix.cs and ConsolePal.Wasi.cs to accept
FileStream instead of SafeFileHandle; use fs.Write(buffer) which handles both seekable
and non-seekable files correctly
- Rename SeekableStdinRedirection test to CanCopyStandardInputToStandardOutput and run on
all non-mobile platforms (not just AnyUnix); simplify via RemoteInvokeOptions.StartInfo
- Simplify SeekableStdoutRedirection test similarly; remove boilerplate try/catch
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/67a83dee-25ae-47d1-ae0f-b4aa1f18265f
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 14, 2026 06:53

CopilotAI commented Apr 14, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please address my feedback

Done in adb2b69. All review feedback addressed:

  • Removed _useFileStreamForIo and extra comments; FileStream is always used for all I/O (handles both seekable and non-seekable correctly)
  • Write() in UnixConsoleStream now calls WriteFromConsoleStream(_fileStream, buffer)
  • WriteFromConsoleStream in both ConsolePal.Unix.cs and ConsolePal.Wasi.cs updated to accept FileStream and call fs.Write(buffer)
  • Tests renamed/simplified and now run on all non-mobile platforms

@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

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
- Fix XML comment in ConsolePal.Wasi.cs Write(FileStream): fd → fs
- Remove _handle field from UnixConsoleStream; FileStream owns handle lifetime
- Remove Flush() override from UnixConsoleStream (base is a nop; bufferSize:0)
- Remove redundant [PlatformSpecific] from two new tests (RemoteExecutor handles it)
- Dispose stdoutHandle before WaitForExit so File.ReadAllText can open the file
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/ba3bd32e-023a-4160-bf27-f0ae05027d8d
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@adamsitnik

Copy link
Copy Markdown
Member

@jozkee@jkotas@stephentoub I would appreciate your review, as I would like to start a longer leave knowing that I leave no known bugs opened.

For context please refer to #126843

This PR is more or less a revert + tests that are going to ensure we are not going to introduce this bug again.

@adamsitnik
adamsitnik enabled auto-merge (squash) April 19, 2026 20:23

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 reverts recent System.Console Unix/WASI I/O changes that used RandomAccess.Read/Write back to the prior Interop.Sys.Read/Write implementation, and adds regression tests for redirected stdin/stdout to seekable files (to prevent hangs/incorrect output).

Changes:

  • Restore Interop.Sys.Read / Interop.Sys.Write-based console stream I/O on Unix and WASI (including the write loop with EPIPE/EAGAIN handling).
  • Add/enable regression tests covering seekable stdin and seekable stdout redirection scenarios.
  • Restore needed interop source inclusions in System.Console.csproj and include ConsoleHandles.cs in the test project.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
src/libraries/System.Console/tests/System.Console.Tests.csprojIncludes ConsoleHandles.cs in the test build.
src/libraries/System.Console/tests/ConsoleHandles.csAdds regression tests for seekable stdin/stdout redirection.
src/libraries/System.Console/src/System/ConsolePal.Wasi.csRestores Interop.Sys.Read/Write + write-loop behavior for WASI.
src/libraries/System.Console/src/System/ConsolePal.Unix.csRestores Interop.Sys.Read/Write + write-loop behavior and cursor-cache updates.
src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csSwitches console stream reads back to ConsolePal.Read (Interop-based).
src/libraries/System.Console/src/System.Console.csprojRe-adds interop source files (Poll/Read/Write) for Unix/WASI builds.

Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Wasi.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs
Comment threadsrc/libraries/System.Console/tests/ConsoleHandles.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
Comment threadsrc/libraries/System.Console/src/System/ConsolePal.Unix.cs
auto-merge was automatically disabled April 19, 2026 20:44

Head branch was pushed to by a user without write access

CopilotAI requested a review from adamsitnikApril 19, 2026 20:45
CopilotAI requested review from Copilot and removed request for CopilotApril 19, 2026 20:50
@adamsitnik
adamsitnik merged commit afd1456 into mainApr 20, 2026
91 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/fix-unix-console-stream-bug branch April 20, 2026 05:57
@adamsitnik

Copy link
Copy Markdown
Member

/backport to release/11.0-preview4

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview4 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@adamsitnik backporting to release/11.0-preview4 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchCreating an empty commit: Initial planApplying: Fix UnixConsoleStream to handle seekable files correctlyUsing index info to reconstruct a base tree...M	src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csM	src/libraries/System.Console/tests/ConsoleHandles.csM	src/libraries/System.Console/tests/System.Console.Tests.csprojFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csCONFLICT (content): Merge conflict in src/libraries/System.Console/src/System/ConsolePal.Unix.ConsoleStream.csAuto-merging src/libraries/System.Console/tests/ConsoleHandles.csCONFLICT (content): Merge conflict in src/libraries/System.Console/tests/ConsoleHandles.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0002 Fix UnixConsoleStream to handle seekable files correctlyError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@adamsitnik

Copy link
Copy Markdown
Member

I am stupid, it was merged before P4 snap so it's already there...

@adamsitnikadamsitnik changed the title Add tests for UnixConsoleStream when stdin/stdout is redirected to a seekable fileFix UnixConsoleStream regression when stdin/stdout is redirected to a seekable fileMay 5, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug in UnixConsoleStream when working with seekable files

4 participants

@adamsitnik@jkotas