[newlib-cygwin] Cygwin: pty: keep interactive console input for native programs via Cygwin
Takashi Yano via Cygwin-cvs <[email protected]>
| Newsgroups | gmane.os.cygwin.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=61b4866baf411c3167cd32d724f35f443dc4e3cd commit 61b4866baf411c3167cd32d724f35f443dc4e3cd Author: Johannes Schindelin <[email protected]> Date: Mon Jul 20 09:43:18 2026 +0000 Cygwin: pty: keep interactive console input for native programs via Cygwin 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]> Reviewed-by: Takashi Yano <[email protected]> Diff: --- 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 6d8f6d5c1..fb49c02b3 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", "");