Skip to content

Preserve saved console modes with redirected stdio - #382

Merged
dscho merged 2 commits into
msys2-3.6.10from
console-output-mode-disables-process-output
Oct 9, 2026
Merged

dscho merged 2 commits into
msys2-3.6.10from
console-output-mode-disables-process-output

Conversation

@dscho

@dscho dscho commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

#379 reports that executing an MSYS2 process with redirected standard streams (such as invoking pacman via Python's subprocess.run(..., capture_output=True)) causes the Windows console output mode to drop from 0x7 to 0x0. This clears ENABLE_PROCESSED_OUTPUT, ENABLE_WRAP_AT_EOL_OUTPUT, and ENABLE_VIRTUAL_TERMINAL_PROCESSING, leaving the hosting console unable to interpret carriage returns, line feeds, and ANSI escape sequences properly.

The root cause lies in the console mode saving and restoration logic: when standard I/O handles are redirected away from the console (for example, into pipes), fhandler_console::open() skipped populating the process-local prev_output_mode_backup (or prev_input_mode_backup), leaving them zero. When the process later exits and console mode restoration runs in close(), that zero backup value is moved into the shared con.prev_output_mode, which the subsequent invocation restores to the Windows console handle, stripping the active mode flags.

To resolve this, we ensure the process-local backup modes are initialized from con.prev_output_mode and con.prev_input_mode unconditionally in fhandler_console::open() under cons_mode_mutex before checking whether standard handles are consoles. A companion test case in the testsuite exercises running commands under redirected stdio to verify that the console mode remains intact across executions.

This addresses #379

dscho added 2 commits October 8, 2026 16:27
With console stdin but captured stdout and stderr, a runtime child can
replace the shared saved output mode with zero. A later invocation
restores that value, rendering CR/LF as glyphs instead of line breaks.
Redirected stdin with console output exposes the corresponding
input-mode omission.

Console handlers restore both modes on close, even with redirected
stdio. Keep their backups valid regardless of whether opening the
handler needs to switch either mode.

Addresses: #379
Fixes: bbd3710 ("Cygwin: console: Set console mode only if
  std{in,out,err} is console")
Assisted-by: GPT-6.1
Signed-off-by: Johannes Schindelin <[email protected]>
(cherry picked from commit 717d7aac57eddbfc2ddb011b249ffe8d87148729)
When stdout and stderr are redirected but stdin remains attached to the
console, starting a Cygwin child via a native launcher must not clear
ENABLE_PROCESSED_OUTPUT.

Protect the behavior restored by 717d7aac57 (Cygwin: console: Preserve
saved modes with redirected stdio) against future regressions.

Addresses: #379
Assisted-by: GPT-6.1
Signed-off-by: Johannes Schindelin <[email protected]>
(cherry picked from commit bff49354caeae98b20fa7ca307bfe6e2649ff490)
@dscho

dscho commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator Author

The PR builds currently fail because staging already published mingw-w64-ucrt-x86_64-llvm-libs 23.1.3-1 (upgraded from 22.1.8-3), which provides libLLVM-23.dll and removes libLLVM-22.dll. That's why rustc.exe exits with code 127. I'll re-run the jobs once that staging problem is resolved, and then mark this PR as ready for review.

EDIT: once mingw-w64-rust is successfully staged, the PR builds should succeed again.

@dscho
dscho marked this pull request as ready for review October 9, 2026 05:37
@dscho
dscho merged commit e0c179b into msys2-3.6.10 Oct 9, 2026
28 of 36 checks passed
@dscho
dscho deleted the console-output-mode-disables-process-output branch October 9, 2026 07:42
lazka pushed a commit to msys2/MSYS2-packages that referenced this pull request Oct 10, 2026
)

msys2/msys2-runtime#379 reports that executing an MSYS2 process with redirected standard streams (such as invoking `pacman` via Python's `subprocess.run(..., capture_output=True)`) causes the Windows console output mode to drop from `0x7` to `0x0`. This clears `ENABLE_PROCESSED_OUTPUT`, `ENABLE_WRAP_AT_EOL_OUTPUT`, and `ENABLE_VIRTUAL_TERMINAL_PROCESSING`, leaving the hosting console unable to interpret carriage returns, line feeds, and ANSI escape sequences properly.

The root cause lies in the console mode saving and restoration logic: when standard I/O handles are redirected away from the console (for example, into pipes), `fhandler_console::open()` skipped populating the process-local `prev_output_mode_backup` (or `prev_input_mode_backup`), leaving them zero. When the process later exits and console mode restoration runs in `close()`, that zero backup value is moved into the shared `con.prev_output_mode`, which the subsequent invocation restores to the Windows console handle, stripping the active mode flags.

To resolve this, we ensure the process-local backup modes are initialized from `con.prev_output_mode` and `con.prev_input_mode` unconditionally in `fhandler_console::open()` under `cons_mode_mutex` before checking whether standard handles are consoles. A companion test case in the testsuite exercises running commands under redirected stdio to verify that the console mode remains intact across executions.

This addresses msys2/msys2-runtime#379

This corresponds to msys2/msys2-runtime#382
github-actions Bot pushed a commit to cygapiss/msys2-apiss that referenced this pull request Oct 10, 2026
…tdio (#6788)

msys2/msys2-runtime#379 reports that executing an MSYS2 process with redirected standard streams (such as invoking `pacman` via Python's `subprocess.run(..., capture_output=True)`) causes the Windows console output mode to drop from `0x7` to `0x0`. This clears `ENABLE_PROCESSED_OUTPUT`, `ENABLE_WRAP_AT_EOL_OUTPUT`, and `ENABLE_VIRTUAL_TERMINAL_PROCESSING`, leaving the hosting console unable to interpret carriage returns, line feeds, and ANSI escape sequences properly.

The root cause lies in the console mode saving and restoration logic: when standard I/O handles are redirected away from the console (for example, into pipes), `fhandler_console::open()` skipped populating the process-local `prev_output_mode_backup` (or `prev_input_mode_backup`), leaving them zero. When the process later exits and console mode restoration runs in `close()`, that zero backup value is moved into the shared `con.prev_output_mode`, which the subsequent invocation restores to the Windows console handle, stripping the active mode flags.

To resolve this, we ensure the process-local backup modes are initialized from `con.prev_output_mode` and `con.prev_input_mode` unconditionally in `fhandler_console::open()` under `cons_mode_mutex` before checking whether standard handles are consoles. A companion test case in the testsuite exercises running commands under redirected stdio to verify that the console mode remains intact across executions.

This addresses msys2/msys2-runtime#379

This corresponds to msys2/msys2-runtime#382

Source: msys2/MSYS2-packages@c98a0dd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant