[newlib-cygwin] Cygwin: pty: Make Ctrl-C work for non-cygwin app in GDB
Takashi Yano via Cygwin-cvs <[email protected]> Fri, 17 Apr 2026 17:41:19 +0000 (GMT)
| Newsgroups | gmane.os.cygwin.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D10a3de565b1= c26a3c600148fa6e478e3501cbbc2 commit 10a3de565b1c26a3c600148fa6e478e3501cbbc2 Author: Takashi Yano <[email protected]> Date: Sat Feb 28 15:48:51 2026 +0900 Cygwin: pty: Make Ctrl-C work for non-cygwin app in GDB =20 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. This patch also fixes the issue that the cygwin debuggee under strace cannot be terminated by Ctrl-C. =20 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. =20 Signed-off-by: Takashi Yano <[email protected]> Reviewed-by: Johannes Schindelin <[email protected]> Reviewed-by: Corinna Vinschen <[email protected]> Diff: --- winsup/cygwin/exceptions.cc | 4 +-- winsup/cygwin/fhandler/pty.cc | 7 +++-- winsup/cygwin/fhandler/termios.cc | 54 ++++++++++++++------------------= ---- winsup/cygwin/local_includes/pinfo.h | 42 ++++++++++++++++++++++++++-- winsup/cygwin/tty.cc | 7 ++--- 5 files changed, 69 insertions(+), 45 deletions(-) diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 21af26ac3..1e129b319 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -1215,8 +1215,8 @@ ctrl_c_handler (DWORD type) if (!pinfo (cygwin_pid (GetCurrentProcessId ()))) return TRUE; =20 - if (type =3D=3D CTRL_C_EVENT && ::cygheap->ctty - && !cygheap->ctty->need_console_handler ()) + if (type =3D=3D CTRL_C_EVENT && !myself->is_cygwin_inferior_being_debugg= ed () + && ::cygheap->ctty && !cygheap->ctty->need_console_handler ()) /* Ctrl-C is handled in fhandler_console::cons_master_thread(). */ return TRUE; =20 diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc index cdfb363c9..80331c36d 100644 --- a/winsup/cygwin/fhandler/pty.cc +++ b/winsup/cygwin/fhandler/pty.cc @@ -384,6 +384,7 @@ atexit_func (void) break; } CloseHandle (h_gdb_inferior); + myself->wpid_debuggee_maybe =3D 0; } } =20 @@ -420,6 +421,7 @@ CreateProcessA_Hooked DuplicateHandle (GetCurrentProcess (), h_gdb_inferior, GetCurrentProcess (), &h_gdb_inferior, 0, 0, DUPLICATE_SAME_ACCESS); + myself->wpid_debuggee_maybe =3D pi->dwProcessId; debug_process =3D !!(f & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)); if (debug_process) mutex_timeout =3D 0; /* to avoid deadlock in GDB */ @@ -459,6 +461,7 @@ CreateProcessW_Hooked DuplicateHandle (GetCurrentProcess (), h_gdb_inferior, GetCurrentProcess (), &h_gdb_inferior, 0, 0, DUPLICATE_SAME_ACCESS); + myself->wpid_debuggee_maybe =3D pi->dwProcessId; debug_process =3D !!(f & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)); if (debug_process) mutex_timeout =3D 0; /* to avoid deadlock in GDB */ @@ -1236,9 +1239,6 @@ fhandler_pty_slave::set_switch_to_nat_pipe (void) { isHybrid =3D true; setup_locale (); - myself->exec_dwProcessId =3D myself->dwProcessId; /* Set this as a m= arker - for tty::nat_fg() - and process_sigs() */ bool stdin_is_ptys =3D GetStdHandle (STD_INPUT_HANDLE) =3D=3D get_ha= ndle (); setup_for_non_cygwin_app (false, NULL, stdin_is_ptys); } @@ -1270,6 +1270,7 @@ fhandler_pty_slave::reset_switch_to_nat_pipe (void) { CloseHandle (h_gdb_inferior); h_gdb_inferior =3D NULL; + myself->wpid_debuggee_maybe =3D 0; mutex_timeout =3D INFINITE; if (isHybrid) { diff --git a/winsup/cygwin/fhandler/termios.cc b/winsup/cygwin/fhandler/ter= mios.cc index 694a5c20f..ca5fa4b7e 100644 --- a/winsup/cygwin/fhandler/termios.cc +++ b/winsup/cygwin/fhandler/termios.cc @@ -338,19 +338,9 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fha= ndler_termios *fh) for (unsigned i =3D 0; i < pids.npids; i++) { _pinfo *p =3D pids[i]; - /* PID_NOTCYGWIN: check this for non-cygwin process. - exec_dwProcessId =3D=3D 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 =3D=3D '\003' && p && p->ctty =3D=3D ttyp->ntty && p->pgid =3D= =3D pgid - && ((p->process_state & PID_NOTCYGWIN) - || ((p->exec_dwProcessId =3D=3D p->dwProcessId) - && ttyp->pty_input_state_eq (tty::to_nat)) - || !(p->process_state & PID_CYGPARENT))) + if (c =3D=3D '\003' && p && p->ctty =3D=3D ttyp->ntty + && (p->is_foreground_special_process (pgid) + || p->is_gdb_with_foreground_non_cygwin_inferior (pgid))) { /* Ctrl-C event will be sent only to the processes attaching to the same console. Therefore, attach to the console to @@ -372,7 +362,7 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhan= dler_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 =3D=3D p->dwProcessId) + || p->is_gdb_with_foreground_non_cygwin_inferior (pgid)) && !ctrl_c_event_sent) { GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0); @@ -390,24 +380,23 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fh= andler_termios *fh) } need_discard_input =3D true; } - if (p && p->ctty =3D=3D ttyp->ntty && p->pgid =3D=3D pgid) + if (p && p->ctty =3D=3D ttyp->ntty) { - if (p->process_state & PID_NOTCYGWIN) - pg_with_nat =3D true; /* The process group has non-cygwin process */ - if (!(p->process_state & PID_NOTCYGWIN)) - need_send_sig =3D true; /* Process which needs signal exists */ - if (!p->cygstarted) - nat_shell =3D true; /* The shell seems to a non-cygwin shell */ - if (p->process_state & PID_TTYIN) - cyg_reader =3D true; /* Theh process is reading the tty */ - if (!p->cygstarted && !(p->process_state & PID_NOTCYGWIN) - && (p->process_state & PID_DEBUGGED)) - with_debugger =3D true; /* inferior is cygwin app */ - if (!(p->process_state & PID_NOTCYGWIN) - && (p->exec_dwProcessId =3D=3D p->dwProcessId) /* Check marker */ - && ttyp->pty_input_state_eq (tty::to_nat) - && p->pid =3D=3D pgid) - with_debugger_nat =3D true; /* inferior is non-cygwin app */ + if (p->pgid =3D=3D pgid) + { + if (p->process_state & PID_NOTCYGWIN) + pg_with_nat =3D true; /* The process group has non-cygwin app */ + if (!(p->process_state & PID_NOTCYGWIN)) + need_send_sig =3D true; /* Process which needs signal exists */ + if (!p->cygstarted) + nat_shell =3D true; /* The shell seems to a non-cygwin shell */ + if (p->process_state & PID_TTYIN) + cyg_reader =3D true; /* Theh process is reading the tty */ + if (p->is_cygwin_inferior_being_debugged ()) + with_debugger =3D true; + } + if (p->is_gdb_with_foreground_non_cygwin_inferior (pgid)) + with_debugger_nat =3D true; } } if ((with_debugger || with_debugger_nat) && need_discard_input) @@ -536,10 +525,9 @@ fhandler_termios::line_edit (const char *rptr, size_t = nread, termios& ti, switch (process_sigs (c, get_ttyp (), this)) { case signalled: - sawsig =3D true; - fallthrough; case not_signalled_but_done: case done_with_debugger: + sawsig =3D true; get_ttyp ()->output_stopped &=3D ~BY_VSTOP; continue; case not_signalled_with_nat_reader: diff --git a/winsup/cygwin/local_includes/pinfo.h b/winsup/cygwin/local_inc= ludes/pinfo.h index d1c9b001b..6f817de6b 100644 --- a/winsup/cygwin/local_includes/pinfo.h +++ b/winsup/cygwin/local_includes/pinfo.h @@ -46,6 +46,9 @@ enum picom =20 class fhandler_pipe; =20 +pid_t create_cygwin_pid (); +pid_t cygwin_pid (DWORD); + class _pinfo { public: @@ -126,10 +129,46 @@ public: bool exists (); const char *_ctty (char *); =20 + /* "Special" here means a non-cygwin process or a process whose parent + is not a cygwin process */ + inline bool is_foreground_special_process (pid_t tty_pgid) + { + if (pgid !=3D tty_pgid) /* The process is background */ + return false; + if (!(process_state & PID_CYGPARENT)) + return true; + return !!(process_state & PID_NOTCYGWIN); + } + inline bool is_foreground_non_cygwin_process (pid_t tty_pgid) + { + if (pgid !=3D tty_pgid) + return false; + return !!(process_state & PID_NOTCYGWIN); + } + inline bool is_gdb_with_foreground_non_cygwin_inferior (pid_t tty_pgid) + { + if (pgid =3D=3D tty_pgid) /* GDB is the foreground process */ + return false; + if (wpid_debuggee_maybe =3D=3D 0) + return false; + /* Below is true for GDB with non-cygwin inferior */ + return !cygwin_pid (wpid_debuggee_maybe); + } + inline bool is_cygwin_inferior_being_debugged () + { + if (cygstarted) + return false; + if (process_state & PID_NOTCYGWIN) + return false; + return !!(process_state & PID_DEBUGGED); + } + /* signals */ HANDLE sendsig; HANDLE exec_sendsig; DWORD exec_dwProcessId; + + DWORD wpid_debuggee_maybe; public: friend class pinfo_minimal; }; @@ -254,9 +293,6 @@ public: void release (); }; =20 -pid_t create_cygwin_pid (); -pid_t cygwin_pid (DWORD); - void pinfo_init (char **, int); extern pinfo myself; =20 diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc index 40b270309..e8083dc1f 100644 --- a/winsup/cygwin/tty.cc +++ b/winsup/cygwin/tty.cc @@ -341,10 +341,9 @@ tty::nat_fg (pid_t pgid) for (unsigned i =3D 0; i < pids.npids; i++) { _pinfo *p =3D pids[i]; - if (p->ctty =3D=3D ntty && p->pgid =3D=3D pgid - && ((p->process_state & PID_NOTCYGWIN) - /* Below is true for GDB with non-cygwin inferior */ - || p->exec_dwProcessId =3D=3D p->dwProcessId)) + if (p->ctty =3D=3D ntty + && (p->is_foreground_non_cygwin_process (pgid) + || p->is_gdb_with_foreground_non_cygwin_inferior (pgid))) return true; } if (pgid > MAX_PID)