[PATCH v2] Cygwin: pty: Make Ctrl-C work for non-cygwin app in GDB

Corinna Vinschen corinna-cygwin@cygwin.com
Tue Apr 14 09:04:02 GMT 2026


Hi Takashi,

two (minor) points:

- is_gdb_with_foreground_non_cygwin_inferior() is defined twice.
  It would probably make sense to move all these inline functions
  is_gdb_with_foreground_non_cygwin_inferior(),
  is_foreground_special_process() and
  is_non_cygwin_foreground_process() into a header.
  pinfo.h might be a good place.

- The check in is_gdb_with_foreground_non_cygwin_inferior() looks
  a bit on the fragile side.  Wouldn't it make sense to check with
  CheckRemoteDebuggerPresent(), or at least, try to?


Thanks,
Corinna

On Mar  9 16:08, Takashi Yano wrote:
> At some point in the past, GDB sets terminal pgid to inferior pid
> when the inferior is running. Moreover, the inferior is non-cygwin
> process, GDB sets the terminal pgid to windows pid of the inferior.
> Due to this behaviour, Ctrl-C does not work if the inferior is a
> non-cygwin app. This is because, the current code sends Ctrl-C to
> GDB only when GDB's pgid equeals to terminal pgid. This patch omit
> checking pgid when recognizing GDB process whose inferior is non-
> cygwin app.
> 
> In addition, to improve the readabiliby of the code, this patch
> introduces inline functions such as:
> is_foreground_special_process (),
> is_gdb_with_foreground_non_cygwin_inferior (), etc.,
> instead of complicated conditions in 'if' clauses.
> 
> Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
> Reviewed-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
> ---
>  winsup/cygwin/fhandler/termios.cc | 62 +++++++++++++++++++++----------
>  winsup/cygwin/tty.cc              | 24 ++++++++++--
>  2 files changed, 63 insertions(+), 23 deletions(-)
> 
> diff --git a/winsup/cygwin/fhandler/termios.cc b/winsup/cygwin/fhandler/termios.cc
> index 694a5c20f..08cab9a01 100644
> --- a/winsup/cygwin/fhandler/termios.cc
> +++ b/winsup/cygwin/fhandler/termios.cc
> @@ -311,6 +311,41 @@ fhandler_termios::echo_erase (int force)
>      doecho ("\b \b", 3);
>  }
>  
> +/* PID_NOTCYGWIN: check this for non-cygwin process.
> +   exec_dwProcessId == dwProcessId:
> +	       check this for GDB with non-cygwin inferior in pty
> +	       without pcon enabled. In this case, the inferior is not
> +	       cygwin process list. This condition is set true as
> +	       a marker for GDB with non-cygwin inferior in pty code.
> +   !PID_CYGPARENT: check this for GDB with cygwin inferior or
> +		   cygwin apps started from non-cygwin shell. */
> +
> +/* "Special" here means a non-cygwin process or a process whose parent
> +   is not a cygwin process */
> +inline static bool
> +is_foreground_special_process (_pinfo *p, pid_t tty_pgid)
> +{
> +  if (!p)
> +    return false;
> +  if (p->pgid != tty_pgid)
> +    return false;
> +  return !((p->process_state & PID_CYGPARENT)
> +	   && !(p->process_state & PID_NOTCYGWIN));
> +}
> +
> +/* exec_dwProcessId == dwProcessId:
> +       check this for GDB with non-cygwin inferior in pty
> +       In this case, the inferior is not cygwin process list.
> +       This condition is set true as a marker for GDB with
> +       non-cygwin inferior in pty code. */
> +inline static bool
> +is_gdb_with_foreground_non_cygwin_inferior (_pinfo *p, tty *ttyp)
> +{
> +  if (p->exec_dwProcessId != p->dwProcessId)
> +    return false;
> +  return ttyp->pty_input_state_eq (tty::to_nat);
> +}
> +
>  /* The basic policy is as follows:
>     - The signal generated by key press will be sent only to cygwin process.
>     - For non-cygwin process, CTRL_C_EVENT will be sent on Ctrl-C. */
> @@ -338,19 +373,9 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhandler_termios *fh)
>    for (unsigned i = 0; i < pids.npids; i++)
>      {
>        _pinfo *p = pids[i];
> -      /* PID_NOTCYGWIN: check this for non-cygwin process.
> -	 exec_dwProcessId == dwProcessId:
> -		     check this for GDB with non-cygwin inferior in pty
> -		     without pcon enabled. In this case, the inferior is not
> -		     cygwin process list. This condition is set true as
> -		     a marker for GDB with non-cygwin inferior in pty code.
> -	 !PID_CYGPARENT: check this for GDB with cygwin inferior or
> -			 cygwin apps started from non-cygwin shell. */
> -      if (c == '\003' && p && p->ctty == ttyp->ntty && p->pgid == pgid
> -	  && ((p->process_state & PID_NOTCYGWIN)
> -	      || ((p->exec_dwProcessId == p->dwProcessId)
> -		  && ttyp->pty_input_state_eq (tty::to_nat))
> -	      || !(p->process_state & PID_CYGPARENT)))
> +      if (c == '\003' && p && p->ctty == ttyp->ntty
> +	  && (is_foreground_special_process (p, pgid)
> +	      || is_gdb_with_foreground_non_cygwin_inferior (p, ttyp)))
>  	{
>  	  /* Ctrl-C event will be sent only to the processes attaching
>  	     to the same console. Therefore, attach to the console to
> @@ -372,7 +397,7 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhandler_termios *fh)
>  	  if (p->process_state & PID_NEW_PG)
>  	    GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, p->dwProcessId);
>  	  else if ((!fh || fh->need_send_ctrl_c_event ()
> -		    || p->exec_dwProcessId == p->dwProcessId)
> +		    || is_gdb_with_foreground_non_cygwin_inferior (p, ttyp))
>  		   && !ctrl_c_event_sent)
>  	    {
>  	      GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0);
> @@ -403,12 +428,11 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhandler_termios *fh)
>  	  if (!p->cygstarted && !(p->process_state & PID_NOTCYGWIN)
>  	      && (p->process_state & PID_DEBUGGED))
>  	    with_debugger = true; /* inferior is cygwin app */
> -	  if (!(p->process_state & PID_NOTCYGWIN)
> -	      && (p->exec_dwProcessId == p->dwProcessId) /* Check marker */
> -	      && ttyp->pty_input_state_eq (tty::to_nat)
> -	      && p->pid == pgid)
> -	    with_debugger_nat = true; /* inferior is non-cygwin app */
>  	}
> +      if (p &&  p->ctty == ttyp->ntty
> +	  && !(p->process_state & PID_NOTCYGWIN)
> +	  && is_gdb_with_foreground_non_cygwin_inferior (p, ttyp))
> +	with_debugger_nat = true; /* inferior is non-cygwin app */
>      }
>    if ((with_debugger || with_debugger_nat) && need_discard_input)
>      {
> diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
> index 0c49dc2bd..acc21c0ca 100644
> --- a/winsup/cygwin/tty.cc
> +++ b/winsup/cygwin/tty.cc
> @@ -331,6 +331,23 @@ tty::wait_fwd ()
>      }
>  }
>  
> +inline static bool
> +is_non_cygwin_foreground_process (_pinfo *p, pid_t pgid)
> +{
> +  if (p->pgid != pgid)
> +    return false;
> +  return !!(p->process_state & PID_NOTCYGWIN);
> +}
> +
> +inline static bool
> +is_gdb_with_foreground_non_cygwin_inferior (_pinfo *p, pid_t pgid)
> +{
> +  if (p->pgid == pgid) /* GDB is the foreground process */
> +    return false;
> +  /* Below is true for GDB with non-cygwin inferior */
> +  return p->exec_dwProcessId == p->dwProcessId;
> +}
> +
>  bool
>  tty::nat_fg (pid_t pgid)
>  {
> @@ -340,10 +357,9 @@ tty::nat_fg (pid_t pgid)
>    for (unsigned i = 0; i < pids.npids; i++)
>      {
>        _pinfo *p = pids[i];
> -      if (p->ctty == ntty && p->pgid == pgid
> -	  && ((p->process_state & PID_NOTCYGWIN)
> -	      /* Below is true for GDB with non-cygwin inferior */
> -	      || p->exec_dwProcessId == p->dwProcessId))
> +      if (p->ctty == ntty
> +	  && (is_non_cygwin_foreground_process (p, pgid)
> +	      || is_gdb_with_foreground_non_cygwin_inferior (p, pgid)))
>  	return true;
>      }
>    if (pgid > MAX_PID)
> -- 
> 2.51.0


More information about the Cygwin-patches mailing list