[newlib-cygwin] Cygwin: pty: Drop nat_fg() check from to_be_read_from_nat_pipe()
Takashi Yano via Cygwin-cvs <[email protected]> Sun, 29 Mar 2026 00:44:16 +0000 (GMT)
| Newsgroups | gmane.os.cygwin.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D6413c19fd85= bd7d6dc42368e22cebe86b730b3b6 commit 6413c19fd85bd7d6dc42368e22cebe86b730b3b6 Author: Takashi Yano <[email protected]> Date: Tue Mar 24 11:08:52 2026 +0900 Cygwin: pty: Drop nat_fg() check from to_be_read_from_nat_pipe() =20 While a non-cygwin app has exited but the stub process has not yet terminated, `nat_fg()` returns false because no non-cygwin app is running. In this window, pty input goes to the cyg pipe. Due to this, the keystroke order is swapped unexpectedly: =20 1) start non-cygwin app 2) press 'a' ('a' goes to nat pipe) 3) non-cygwin app exits 4) press 'b' ('b' goes to cyg pipe) 5) the stub process for non-cygwin app transfers input in nat pipe to cyg pipe ('a' goes to cyg pipe) 6) the result in the cyg pipe is "ba" =20 Fix this by dropping the `nat_fg()` check from `to_be_read_from_nat_pipe()`. The function now returns true when `!pcon_start && switch_to_nat_pipe && !masked`. Each component has a specific purpose: =20 - `!pcon_start`: keystrokes go through the CSI6n response handler during pseudo console initialization rather than the fast path. - `switch_to_nat_pipe`: this session-level flag stays true from `setup_for_non_cygwin_app()` through `cleanup_for_non_cygwin_app()`, spanning the entire native process lifetime including the post-exit cleanup window. - `!masked` (`TTY_SLAVE_READING` event does not exist): keystrokes go to the Cygwin pipe when a Cygwin process is actively reading from the slave, since that process expects POSIX-processed input. =20 Removing `nat_fg()` is safe because conhost's input buffer accumulates keystrokes as INPUT_RECORDs during the post-exit window, and `transfer_input(to_cyg)` in `cleanup_for_non_cygwin_app()` reads them back via `ReadConsoleInputA()` and writes them to the cyg pipe. Those transferred bytes then go through `line_edit()` in the master's forward thread (via `input_transferred_to_cyg` from an earlier patch in this series), ensuring proper POSIX line discipline processing. =20 Additionally, add a `nat_fg()` check to the disable_pcon transfer path in `master::write()`. That transfer moves cyg pipe data to the nat pipe when a Cygwin child exits and a native process regains the foreground with pcon disabled. Without pcon, there is no conhost buffer to accumulate keystrokes (the nat pipe is a raw pipe), so keystrokes must only go there when a native process is genuinely in the foreground and ready to read them. The `nat_fg()` guard prevents the transfer from stealing readline's data during the post-exit window. =20 Fixes: f20641789427 ("Cygwin: pty: Reduce unecessary input transfer.") Signed-off-by: Takashi Yano <[email protected]> Reviewed-by: Johannes Schindelin <[email protected]> Diff: --- winsup/cygwin/fhandler/pty.cc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc index 18285b874..14e355ce5 100644 --- a/winsup/cygwin/fhandler/pty.cc +++ b/winsup/cygwin/fhandler/pty.cc @@ -1309,14 +1309,8 @@ fhandler_pty_common::to_be_read_from_nat_pipe (void) goto out; } =20 - if (!pinfo (get_ttyp ()->getpgid ())) - /* GDB may set invalid process group for non-cygwin process. */ - { - ret =3D true; - goto out; - } + ret =3D true; /* !pcon_start && switch_to_nat_pipe && !masked */ =20 - ret =3D get_ttyp ()->nat_fg (get_ttyp ()->getpgid ()); out: ReleaseMutex (pipe_sw_mutex); return ret; @@ -2381,6 +2375,7 @@ fhandler_pty_master::write (const void *ptr, size_t l= en) /* This input transfer is needed when cygwin-app which is started from non-cygwin app is terminated if pseudo console is disabled. */ if (to_be_read_from_nat_pipe () && !get_ttyp ()->pcon_activated + && get_ttyp ()->nat_fg (get_ttyp ()->getpgid ()) && get_ttyp ()->pty_input_state =3D=3D tty::to_cyg) { acquire_attach_mutex (mutex_timeout);