[PATCH] Cygwin: pty: Fix input transfer when multiple non-cygwin apps exist
Johannes Schindelin
Johannes.Schindelin@gmx.de
Fri Mar 27 11:03:40 GMT 2026
Hi Takashi,
On Tue, 10 Mar 2026, Takashi Yano wrote:
> Currently, if two non-cygwin process exist, one is nat pipe owner
> and the other is not, and if the second process (not a nat pipe
> owner) is terminated first, the first process (the nat pipe owner)
> looses the input. This is because transfer_input() is wrongly called
> in cleanup_for_non_cygwin_app().
>
> With this patch, in cleanup_for_non_cygwin_app(), transfer_input()
> is called only when the current process is a nat pipe owner to
> solve this problem.
>
> Fixes: f9542a2e8e75 ("Cygwin: pty: Re-fix the last bug regarding nat-pipe.")
> Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
> Reviewed-by:
The patch is clean and as far as I can tell correct, but we need to talk
about the commit message. It might be correct in what it says, yet I
consider it incomplete because it leaves too many questions open that I,
for one, had a grand old time figuring out after scratching my head
bloody. So I would like to propose the following commit message instead:
-- snip --
Cygwin: pty: Fix input transfer when multiple non-cygwin apps exist
Cygwin maintains POSIX line discipline for its own processes: input
goes through `line_edit()` before reaching the reading process. Native
(non-Cygwin) processes must not receive line-edited input; they expect
raw console input instead. To support both, the PTY keeps two
independent pipe pairs for input: a "cyg" pipe for Cygwin processes
and a "nat" pipe for native ones. The runtime switches between the two
as the foreground process changes.
The PTY tracks which process "owns" the nat pipe session via the
shared-memory field `nat_pipe_owner_pid`. Only one process is the
owner at any time. When `setup_for_non_cygwin_app()` finds that the
current owner is still alive, it leaves ownership with that process
rather than claiming it for the new one.
This means that a Cygwin-spawned native process can go through
`cleanup_for_non_cygwin_app()` without being the nat pipe owner.
Before this fix, that cleanup called `transfer_input(to_cyg)`
unconditionally, draining the pseudo console's input buffer even
though another process still owned the session. Keystrokes that the
user had typed were moved to the cyg pipe prematurely, so the actual
owner found an empty console input buffer and appeared to lose all
input.
When looking for the next owner of the console in
`cleanup_for_non_cygwin_app()` (via `get_winpid_to_hand_over()`), and
when transferring the input back to the cyg pipe, guard both with a
`nat_pipe_owner_self()` check so that only the actual owner performs
these operations. Non-owner processes skip straight to detaching from
the pseudo console without disturbing the input buffer.
Fixes: f9542a2e8e75 ("Cygwin: pty: Re-fix the last bug regarding nat-pipe.")
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Reviewed-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
-- snap --
What do you think?
Ciao,
Johannes
> ---
> winsup/cygwin/fhandler/pty.cc | 21 ++++++++++++---------
> 1 file changed, 12 insertions(+), 9 deletions(-)
>
> diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc
> index 56b573c8d..aaad47ca9 100644
> --- a/winsup/cygwin/fhandler/pty.cc
> +++ b/winsup/cygwin/fhandler/pty.cc
> @@ -4575,16 +4575,19 @@ fhandler_pty_slave::cleanup_for_non_cygwin_app (handle_set_t *p, tty *ttyp,
> {
> ttyp->wait_fwd ();
> WaitForSingleObject (p->pipe_sw_mutex, INFINITE);
> - DWORD switch_to = get_winpid_to_hand_over (ttyp, force_switch_to);
> - if ((!switch_to && (ttyp->pcon_activated || stdin_is_ptys))
> - && ttyp->pty_input_state_eq (tty::to_nat))
> + if (nat_pipe_owner_self (ttyp->nat_pipe_owner_pid))
> {
> - WaitForSingleObject (p->input_mutex, mutex_timeout);
> - acquire_attach_mutex (mutex_timeout);
> - transfer_input (tty::to_cyg, p->from_master_nat, ttyp,
> - p->input_available_event);
> - release_attach_mutex ();
> - ReleaseMutex (p->input_mutex);
> + DWORD switch_to = get_winpid_to_hand_over (ttyp, force_switch_to);
> + if ((!switch_to && (ttyp->pcon_activated || stdin_is_ptys))
> + && ttyp->pty_input_state_eq (tty::to_nat))
> + {
> + WaitForSingleObject (p->input_mutex, mutex_timeout);
> + acquire_attach_mutex (mutex_timeout);
> + transfer_input (tty::to_cyg, p->from_master_nat, ttyp,
> + p->input_available_event);
> + release_attach_mutex ();
> + ReleaseMutex (p->input_mutex);
> + }
> }
> if (ttyp->pcon_activated)
> close_pseudoconsole (ttyp, force_switch_to);
> --
> 2.51.0
>
>
More information about the Cygwin-patches
mailing list