Re: [PATCH v4] Cygwin: console: Fix undesired mode change at exit of non-cygwin apps
Takashi Yano <[email protected]> Thu, 16 Jul 2026 16:47:07 +0900
| Newsgroups | gmane.os.cygwin.patches |
|---|---|
| Message-ID | <[email protected]> |
On Thu, 16 Jul 2026 16:36:18 +0900
Takashi Yano wrote:
> 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 apps modifying
> console mode simultaneously, this patch also introduce a mutex
> named `cons_mode_mutex`.
>
> 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.
> v4: Guard all mode changes in console by cons_mode_mutex.
>
> winsup/cygwin/fhandler/console.cc | 87 ++++++++++++++++++++++++-
> winsup/cygwin/local_includes/fhandler.h | 2 +
> 2 files changed, 86 insertions(+), 3 deletions(-)
>
> diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
> index d4c87f29f..5b9a87ebd 100644
> --- a/winsup/cygwin/fhandler/console.cc
> +++ b/winsup/cygwin/fhandler/console.cc
> @@ -977,15 +977,59 @@ fhandler_console::setup_for_non_cygwin_app ()
> console mode. */
> if (get_ttyp ()->getpgid () == myself->pgid)
> {
> + 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);
> }
> }
>
> +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;
> +
> + WaitForSingleObject (p->cons_mode_mutex, INFINITE);
> + if (num_active_non_cygwin_apps (cygheap->ctty->tc()->pgid))
> + {
> + ReleaseMutex (p->cons_mode_mutex);
> + CloseHandle (p->cons_mode_mutex);
Closing cons_mode_mutex here is incorrect. Sorry.
> + return;
> + }
> +
> const _minor_t unit = p->unit;
> termios dummy = {0, };
> termios *ti = shared_console_info[unit] ?
[...]
--
Takashi Yano <[email protected]>