[PATCH] Cygwin: pty: keep interactive console input for native programs via Cygwin
"Johannes Schindelin via GitGitGadget" <[email protected]> Mon, 20 Jul 2026 09:43:18 +0000
| Newsgroups | gmane.os.cygwin.patches |
|---|---|
| Message-ID | <[email protected]> |
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]> --- Fix a regression on cygwin/master I noticed this regression in Git for Windows' fork, to which I had backported the faulty commit from Cygwin's master branch. Published-As: https://github.com/cygwingitgadget/cygwin/releases/tag/pr-8%2Fdscho%2Ffix-nat-handle-leakfix-cygwin-v1 Fetch-It-Via: git fetch https://github.com/cygwingitgadget/cygwin pr-8/dscho/fix-nat-handle-leakfix-cygwin-v1 Pull-Request: https://github.com/cygwingitgadget/cygwin/pull/8 winsup/cygwin/fhandler/pty.cc | 44 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc index f3df55f34..37a480933 100644 --- a/winsup/cygwin/fhandler/pty.cc +++ b/winsup/cygwin/fhandler/pty.cc @@ -1220,26 +1220,6 @@ fhandler_pty_slave::open (int flags, mode_t) release_attach_mutex (); } - set_open_status (); - return 1; - -err: - if (GetLastError () == ERROR_FILE_NOT_FOUND) - set_errno (ENXIO); - else - __seterrno (); -err_no_errno: - termios_printf (errmsg); -err_no_msg: - for (HANDLE **h = handles; *h; h++) - if (**h && **h != INVALID_HANDLE_VALUE) - CloseHandle (**h); - return 0; -} - -bool -fhandler_pty_slave::open_setup (int flags) -{ if (get_ttyp ()->pcon_activated) { HANDLE pcon_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE, @@ -1255,8 +1235,8 @@ fhandler_pty_slave::open_setup (int flags) 0, TRUE, DUPLICATE_SAME_ACCESS); if (ok_in && ok_out) { - /* Close the cyg master-side handles open() installed before - replacing them, so they do not leak. */ + /* Replace these before open_with_arch() copies them into the + archetype shared by all pty slave fhandlers. */ CloseHandle (get_handle_nat ()); CloseHandle (get_output_handle_nat ()); set_handle_nat (new_in); @@ -1273,6 +1253,26 @@ fhandler_pty_slave::open_setup (int flags) } } + set_open_status (); + return 1; + +err: + if (GetLastError () == ERROR_FILE_NOT_FOUND) + set_errno (ENXIO); + else + __seterrno (); +err_no_errno: + termios_printf (errmsg); +err_no_msg: + for (HANDLE **h = handles; *h; h++) + if (**h && **h != INVALID_HANDLE_VALUE) + CloseHandle (**h); + return 0; +} + +bool +fhandler_pty_slave::open_setup (int flags) +{ set_flags ((flags & ~O_TEXT) | O_BINARY); myself->set_ctty (this, flags); report_tty_counts (this, "opened", ""); base-commit: 524d75ff73986b263161665af771cc90e55b5e01 -- cygwingitgadget