[PATCH v3] Cygwin: console: Fix undesired mode change at exit of non-cygwin apps
Takashi Yano <[email protected]> Thu, 16 Jul 2026 15:58:43 +0900
| Newsgroups | gmane.os.cygwin.patches |
|---|---|
| Message-ID | <[email protected]> |
Previously, if two non-cygwin apps are started and one of them
exits first, the other one loosed appropriate console mode, since
the first one restored it to tty::cygwin. This patch counts the
active console process whose pgid is pgid of the tty and if the
result is zero (means the last non-cygwin foreground process),
restore console mode. To avoid race issue between non-cygwin apps
exiting simultaneously, this patch also introduce a named mutex
used only in (setup|cleanup)_for_non_cygwin_app().
Fixes: 48285aa36c2c ("Cygwin: console: Fix handling of Ctrl-S in Win7.")
Signed-off-by: Takashi Yano <[email protected]>
Reviewed-by: Johannes Schindelin <[email protected]>
---
v2: Stop counting up/down the counter by itself.
Use num_active_non_cygwin_apps() instead.
v3: Guard setup_for_non_cygwin_app() by cons_mode_mutex as well.
winsup/cygwin/fhandler/console.cc | 52 +++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
index d4c87f29f..62650726d 100644
--- a/winsup/cygwin/fhandler/console.cc
+++ b/winsup/cygwin/fhandler/console.cc
@@ -977,15 +977,65 @@ fhandler_console::setup_for_non_cygwin_app ()
console mode. */
if (get_ttyp ()->getpgid () == myself->pgid)
{
+ char buf[MAX_PATH];
+ shared_name (buf, "cygcons.cons_mode.mutex", unit);
+ HANDLE cons_mode_mutex = CreateMutex (&sec_none, FALSE, buf);
+ WaitForSingleObject (cons_mode_mutex, INFINITE);
set_disable_master_thread (true, this);
set_input_mode (tty::native, &tc ()->ti, get_handle_set ());
set_output_mode (tty::native, &tc ()->ti, get_handle_set ());
+ ReleaseMutex (cons_mode_mutex);
+ CloseHandle (cons_mode_mutex);
}
}
+static int
+num_active_non_cygwin_apps (pid_t pgid)
+{
+ tmp_pathbuf tp;
+ DWORD *list = (DWORD *) tp.c_get ();
+ const DWORD buf_size = NT_MAX_PATH / sizeof (DWORD);
+
+ DWORD buf_size1 = 1;
+ DWORD num;
+ /* The buffer of too large size does not seem to be expected by new condrv.
+ https://github.com/microsoft/terminal/issues/18264#issuecomment-2515448548
+ Use the minimum buffer size in the loop. */
+ while ((num = GetConsoleProcessList (list, buf_size1)) > buf_size1)
+ {
+ if (num > buf_size)
+ return 0;
+ buf_size1 = num;
+ }
+ if (num == 0)
+ return 0;
+
+ int cnt = 0;
+ for (DWORD i = 0; i < num; i++)
+ {
+ pinfo p (cygwin_pid (list[i]));
+ if (!!p && p->pgid == pgid && ISSTATE (p, PID_NOTCYGWIN))
+ cnt++;
+ }
+ return cnt;
+}
+
void
fhandler_console::cleanup_for_non_cygwin_app (handle_set_t *p)
{
+ if (cygheap->ctty->tc()->pgid != myself->pgid)
+ return;
+ char buf[MAX_PATH];
+ shared_name (buf, "cygcons.cons_mode.mutex", p->unit);
+ HANDLE cons_mode_mutex = CreateMutex (&sec_none, FALSE, buf);
+ WaitForSingleObject (cons_mode_mutex, INFINITE);
+ if (num_active_non_cygwin_apps (cygheap->ctty->tc()->pgid))
+ {
+ ReleaseMutex (cons_mode_mutex);
+ CloseHandle (cons_mode_mutex);
+ return;
+ }
+
const _minor_t unit = p->unit;
termios dummy = {0, };
termios *ti = shared_console_info[unit] ?
@@ -999,6 +1049,8 @@ fhandler_console::cleanup_for_non_cygwin_app (handle_set_t *p)
set_output_mode (conmode, ti, p);
if (con.curr_input_mode != conmode)
set_input_mode (conmode, ti, p);
+ ReleaseMutex (cons_mode_mutex);
+ CloseHandle (cons_mode_mutex);
}
/* Return the tty structure associated with a given tty number. If the
--
2.51.0