[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", "");
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.