Re: [PATCH] Cygwin: pty: keep interactive console input for native programs via Cygwin

Takashi Yano <[email protected]>
Newsgroups gmane.os.cygwin.patches
Message-ID <[email protected]>
Hi Johannes,

On Wed, 22 Jul 2026 01:18:16 +0200 (CEST)
Johannes Schindelin wrote:
> Hi Takashi,
> 
> On Tue, 21 Jul 2026, Takashi Yano wrote:
> 
> > On Mon, 20 Jul 2026 09:43:18 +0000
> > "Johannes Schindelin  wrote:
> > > From: Johannes Schindelin <[email protected]>
> > > 
> > > 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 <[email protected]>
> > 
> > How can I reproduce the issue in cygwin?
> > I tried:
> > $ 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
> > False
> > $ '/cygdrive/c/Program Files/Git/mingw64/bin/git.exe' -c 'alias.console-probe=!powershell.exe -NoLogo -NoProfile -Command "
> >     Write-Output ([Console]::IsInputRedirected)
> >     try {
> >       [void][Console]::KeyAvailable
> >       exit 0
> >     } catch {
> >       exit 1
> >     }
> >   "' console-probe
> > False
> > $ '/cygdrive/c/Program Files/Git/bin/git.exe'  -c 'alias.console-probe=!powershell.exe -NoLogo -NoProfile -Command "
> >     Write-Output ([Console]::IsInputRedirected)
> >     try {
> >       [void][Console]::KeyAvailable
> >       exit 0
> >     } catch {
> >       exit 1
> >     }
> >   "' console-probe
> > False
> > $
> > 
> > All look successfull on master branch...
> 
> I'm sorry, I should have clarified several things:
> 
> - First of all, this reproducer has to be run in MinTTY.
> 
> - Second, it does _not_ actually reproduce the bug with the Cygwin runtime
>   built from cygwin/master. It only reproduces in Git for Windows' flavor
>   of the MSYS2 runtime because of the backports of:
> 
>   - 6eed1ef748 (Cygwin: pty: detect pcon-backed pty for non-Cygwin-spawned
>     children, 2026-04-30)
> 
>   - b34394d456 (Cygwin: pty: Fixup pty state after a cygwin app exits,
>     2026-06-13)
> 
>   - 60a88896dc (Cygwin: pty: do not leak nat handles when adopting the
>     pcon's in open_setup(), 2026-06-25)
> 
>   The combination of these three commits is the trifecta that surfaces
>   that bug, and the same issue _does_ reproduce when cherry-picking those
>   backports on top of `cygwin-3_6-branch`. For your convenience, I have
>   pushed that branch to
>   https://github.com/dscho/msys2-runtime/commits/minimal-backports-for-nat-leakfix-bug
> 
> - The reproducer not only requires the use of Git for Windows' `git.exe`
>   (as an easy way to run a Win32 program that calls a non-Win32 Bash that
>   in turn calls a Win32 program again, I should probably have come up with
>   a command-line that uses powershell.exe instead of git.exe). In
>   addition, `git.exe`'s _strong_ preference for _its own_ `sh.exe` needs
>   to be side-stepped by defining `MSYSTEM=MINGW64` (which stops that
>   PATH-editing logic of `git.exe`):
> 
>   MSYSTEM=MINGW64 PATH=/cygdrive/c/Program\ Files/Git/mingw64/bin:/usr/bin:$PATH 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

Thanks. I was able to reproduce the issue. Belatedly, Ill review your patch.
Please give me a little more time.

-- 
Takashi Yano <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.