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]>