Keep interactive console input for native programs when spawned via the MSYS2 runtime - #138
Merged
Conversation
…ygwin
Currently, when a native Windows program starts a Cygwin program while a
pseudo console is active, and the Cygwin program then starts another
native Windows program, the final program can lose access to console
input. It then behaves as though its standard input were redirected
instead of remaining interactive.
For example, a native `git.exe` may invoke shell aliases (i.e. execute a
shell command) that would in turn call interactive Git commands who
would no longer work because their standard input appeared to be
redirected. This can be demonstrated as follows:
git -c 'alias.console-probe=!powershell.exe -NoLogo -NoProfile -Command "
Write-Output ([Console]::IsInputRedirected)
try {
[void][Console]::KeyAvailable
exit 0
} catch {
exit 1
}
"' console-probe
Running this command with a Win32 version of `git.exe` currently prints
`True` and exits with exit code 1. In the latest official release, where
this bug is not present, it prints `False` and results in exit code 0.
The reason is to be fonud in the archetype code. Reminder: For each
pseudo terminal (pty), the archetype is the shared pty fhandler that
owns the underlying native handles and supplies them to every
per-file-descriptor fhandler for that pty.
`open_with_arch()` calls `open()`, copies the first pty fhandler's state
into the archetype, and then calls `open_setup()`. At that stage, pcon
handle adoption already took place in `open_setup()`. This was not
anticipated by 60a88896dc (Cygwin: pty: do not leak nat handles when
adopting the pcon's in open_setup(), 2026-06-25), which tried to fix a
leak by closing the superseded native handles as they were replaced in
`open_setup()`. Because `open_with_arch()` had already copied those
handle values into the archetype, closing them invalidated the
archetype's copies.
The archetype therefore retained stale values for those closed handles,
which later pty fd fhandlers would inherit. If Windows reuses one of
those values for a newly duplicated pcon handle, closing the stale value
closes the new handle instead. The nested native program then receives
unusable console input.
Preserve usable console input by moving the unchanged transactional pcon
handle adoption to `open()`, before the archetype snapshot. The archetype
then receives valid pcon handles, all pty fd fhandlers inherit live
handles, and the superseded raw pipe handles are closed exactly once.
This commit is best viewed with `--color-moved`.
Fixes: 60a88896dce0 ("Cygwin: pty: do not leak nat handles when
adopting the pcon's in open_setup()")
Assisted-by: GPT-5.6 Sol
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When native `git.exe` runs a `!` alias under `mintty`, it starts `sh.exe`, which may in turn launch another native program. A pseudo console regression made that program see standard input as redirected, causing console APIs such as `[Console]::KeyAvailable` to fail. The existing `mintty` grandchild-input test is the right home for a regression test to catch such a bug because it already launches an interactive `mintty` session and exercises native/Cygwin/native process chains, while the Git invocation itself exercises the relevant alias path. Keep the process chain attached to `mintty` and use PowerShell's file APIs to persist the observations. Shell redirection would replace Git's standard handles before pseudo console setup and mask the regression. Discard stale results so repeated local runs cannot pass spuriously. Assisted-by: GPT 5.6 Sol Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Use a more robust way to verify the long clone. Assisted-by: GPT-5.6 Sol Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Prevent cleanup from hanging by directing `exit` to the test's recorded PowerShell window and waiting for it to close before removing the worktree. Assisted-by: GPT-5.6 Sol Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Avoid false interrupt timeouts by waiting until the shell alias confirms `sleep` is running, then reactivating the recorded PowerShell window before sending Ctrl+C. Assisted-by: GPT-5.6 Sol Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Avoid false clone timeouts by treating the explicit exit-code marker as sufficient completion evidence instead of requiring a clean PowerShell prompt, because the buffer-export hotkey can append `[24~` to it. Assisted-by: GPT-5.6 Sol Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Windows 2025 runners intermittently drop a single synthesized Ctrl+C or
`exit`. Screen-buffer polling can also miss the short-lived clone
`ssh.exe`, or be polluted by terminal key sequences. A dropped clone
interrupt lets a fast localhost clone complete normally. Interrupted Git
cleanup may also leave harmless empty
`.git/{objects,refs}` scaffolding because Windows delete-pending handles
can make `rmdir` lose a race.
Use exact process ownership, rather than ambient process names or screen
contents, as the invariant. Subscribe before clone launch and identify only
the `ssh.exe` carrying the test's unique key path. Track and revalidate the
exact owned PIDs. Restart and clean up only `sshd` PIDs launched by the test.
Do not assume that unrelated Git, SSH, or `sshd` processes are absent, and
never stop any process by name.
Refocus and reissue Ctrl+C until the exact clone `ssh.exe` exits. Treat
surviving files as failures, but tolerate and remove empty scaffolding.
Reissue `exit` until the recorded window closes. Use an explicit exit-code
marker for the successful clone instead of fragile terminal-output ordering.
Claude Opus 4.8 instrumented dropped input: quick Ctrl+C was delivered in
9/12 attempts and dropped in 3/12. Deliberate key-down/up still dropped
1/12. Its second internal stress attempt passed 20/20.
The committed debug-branch source then independently passed the initial
Windows 2025 20-run gate. Copilot steps were skipped, and no error text
appeared in any iteration log. The ported feature-branch source matches the
tested source except for one behavior-neutral line wrap. It passes the
AutoHotkey parser and hygiene checks.
Assisted-by: Claude Opus 4.8
Assisted-by: GPT-5.6 Sol
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
dscho
force-pushed
the
fix-nat-handle-leakfix
branch
from
July 19, 2026 20:38
a781eff to
55abf76
Compare
Member
Author
|
/open pr The workflow run was started |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I introduced a regression in #131: When a native Windows program starts a Cygwin program while a pseudo console is active, and the Cygwin program then starts another native Windows program, the final program can lose access to console input. It then behaves as though its standard input were redirected instead of remaining interactive.
For example, a native
git.exemay invoke shell aliases (i.e. execute a shell command) that would in turn call interactive Git commands who would no longer work because their standard input appeared to be redirected. This can be demonstrated as follows:Running this command with a Win32 version of
git.execurrently printsTrueand exits with exit code 1. In the latest official release, where this bug is not present, it printsFalseand results in exit code 0.Let's fix this.