[PATCH v3 6/6] Cygwin: pty: Guard to_be_read_from_nat_pipe() by pipe_sw_mutex
Takashi Yano
takashi.yano@nifty.ne.jp
Thu Mar 19 10:55:20 GMT 2026
If to_be_read_from_nat_pipe() is called during pipe switching between
cygwin pipe and nat pipe, the return value mignt not as expected due
to incomplete state change. With this patch, to_be_read_from_nat_pipe()
is guarded by pipe_sw_mutex to avoid that. In addition, duration of
the acquiring the pipe_sw_mutex is reduced to avoid deadlock.
Fixes: bb4285206207 ("Cygwin: pty: Implement new pseudo console support.")
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Reviewed-by:
---
winsup/cygwin/fhandler/pty.cc | 50 +++++++++++++++++++++++++----------
1 file changed, 36 insertions(+), 14 deletions(-)
diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc
index 0de6ec007..0c50e50f5 100644
--- a/winsup/cygwin/fhandler/pty.cc
+++ b/winsup/cygwin/fhandler/pty.cc
@@ -1311,22 +1311,44 @@ fhandler_pty_slave::mask_switch_to_nat_pipe (bool mask, bool xfer)
bool
fhandler_pty_common::to_be_read_from_nat_pipe (void)
{
+ /* If the slave is in setup_pseudoconsole(), pipe_sw_mutex cannot
+ be acquired because the slave has it. In this case pcon_start
+ will be asserted. During pcon_start, other input than response
+ to CSI6n should be go to cyg-pipe. So, wait for pcon_start and
+ return false. */
+ while (WaitForSingleObject (pipe_sw_mutex, 0) == WAIT_TIMEOUT)
+ if (get_ttyp ()->pcon_start)
+ return false;
+ else
+ yield ();
+
+ bool ret = false;
if (!get_ttyp ()->switch_to_nat_pipe)
- return false;
+ goto out;
- char name[MAX_PATH];
- shared_name (name, TTY_SLAVE_READING, get_minor ());
- HANDLE masked = OpenEvent (READ_CONTROL, FALSE, name);
- CloseHandle (masked);
+ do
+ {
+ char name[MAX_PATH];
+ shared_name (name, TTY_SLAVE_READING, get_minor ());
+ HANDLE masked = OpenEvent (READ_CONTROL, FALSE, name);
+ CloseHandle (masked);
- if (masked) /* The foreground process is cygwin process */
- return false;
+ if (masked) /* The foreground process is cygwin process */
+ goto out;
+ }
+ while (false);
if (!pinfo (get_ttyp ()->getpgid ()))
/* GDB may set invalid process group for non-cygwin process. */
- return true;
+ {
+ ret = true;
+ goto out;
+ }
- return get_ttyp ()->nat_fg (get_ttyp ()->getpgid ());
+ ret = get_ttyp ()->nat_fg (get_ttyp ()->getpgid ());
+out:
+ ReleaseMutex (pipe_sw_mutex);
+ return ret;
}
void
@@ -3948,7 +3970,6 @@ fhandler_pty_slave::term_has_pcon_cap (const WCHAR *env)
goto maybe_dumb;
/* Check if terminal has CSI6n */
- WaitForSingleObject (pipe_sw_mutex, INFINITE);
WaitForSingleObject (input_mutex, mutex_timeout);
/* Set pcon_activated and pcon_start so that the response
will sent to io_handle_nat rather than io_handle. */
@@ -3984,7 +4005,6 @@ fhandler_pty_slave::term_has_pcon_cap (const WCHAR *env)
while (len);
get_ttyp ()->pcon_activated = false;
get_ttyp ()->nat_pipe_owner_pid = 0;
- ReleaseMutex (pipe_sw_mutex);
if (len == 0)
goto not_has_csi6n;
@@ -4000,7 +4020,6 @@ not_has_csi6n:
get_ttyp ()->pcon_start = false;
get_ttyp ()->pcon_activated = false;
ReleaseMutex (input_mutex);
- ReleaseMutex (pipe_sw_mutex);
maybe_dumb:
get_ttyp ()->pcon_cap_checked = true;
return false;
@@ -4318,7 +4337,6 @@ fhandler_pty_slave::cleanup_for_non_cygwin_app (handle_set_t *p, tty *ttyp,
DWORD force_switch_to)
{
ttyp->wait_fwd ();
- WaitForSingleObject (p->pipe_sw_mutex, INFINITE);
if (nat_pipe_owner_self (ttyp->nat_pipe_owner_pid))
{
DWORD switch_to = get_winpid_to_hand_over (ttyp, force_switch_to);
@@ -4334,6 +4352,7 @@ fhandler_pty_slave::cleanup_for_non_cygwin_app (handle_set_t *p, tty *ttyp,
ReleaseMutex (p->input_mutex);
}
}
+ WaitForSingleObject (p->pipe_sw_mutex, INFINITE);
if (ttyp->pcon_activated)
close_pseudoconsole (ttyp, force_switch_to);
else
@@ -4352,6 +4371,7 @@ fhandler_pty_slave::setpgid_aux (pid_t pid)
if (!was_nat_fg && nat_fg && get_ttyp ()->switch_to_nat_pipe
&& get_ttyp ()->pty_input_state_eq (tty::to_cyg))
{
+ ReleaseMutex (pipe_sw_mutex);
WaitForSingleObject (input_mutex, mutex_timeout);
acquire_attach_mutex (mutex_timeout);
transfer_input (tty::to_nat, get_handle (), get_ttyp (),
@@ -4362,6 +4382,7 @@ fhandler_pty_slave::setpgid_aux (pid_t pid)
else if (was_nat_fg && !nat_fg && get_ttyp ()->switch_to_nat_pipe
&& get_ttyp ()->pty_input_state_eq (tty::to_nat))
{
+ ReleaseMutex (pipe_sw_mutex);
bool attach_restore = false;
HANDLE from = get_handle_nat ();
DWORD resume_pid = 0;
@@ -4389,7 +4410,8 @@ fhandler_pty_slave::setpgid_aux (pid_t pid)
release_attach_mutex ();
ReleaseMutex (input_mutex);
}
- ReleaseMutex (pipe_sw_mutex);
+ else
+ ReleaseMutex (pipe_sw_mutex);
}
bool
--
2.51.0
More information about the Cygwin-patches
mailing list