[PATCH] Cygwin: pty, console: Add a workaround for GDB SIGINT handling.

Takashi Yano takashi.yano@nifty.ne.jp
Wed Feb 23 17:47:28 GMT 2022


- The inferior of the GDB cannot be continued after SIGINT even
  though nopass option is set. This seems because cygwin GDB does
  not support hooking cygwin signal. Therefore, a workaround for
  GDB is added. With this patch, only CTRL_C_EVENT is sent to the
  GDB inferior by Ctrl-C and sending SIGINT is omitted. Note that
  "handle SIGINT (no)pass" command does not take effect even with
  or without this patch.
---
 winsup/cygwin/fhandler.h          |  3 ++-
 winsup/cygwin/fhandler_console.cc |  1 +
 winsup/cygwin/fhandler_termios.cc | 29 ++++++++++++++++++++++++++++-
 winsup/cygwin/fhandler_tty.cc     |  9 ++++++++-
 4 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index b252b6e1c..7ddf7e450 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1906,7 +1906,8 @@ class fhandler_termios: public fhandler_base
     signalled,
     not_signalled,
     not_signalled_but_done,
-    not_signalled_with_nat_reader
+    not_signalled_with_nat_reader,
+    done_with_debugger
   };
 
  public:
diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc
index a7516f238..b290cde08 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -251,6 +251,7 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
 		{
 		case signalled:
 		case not_signalled_but_done:
+		case done_with_debugger:
 		  processed = true;
 		  ttyp->output_stopped = false;
 		  if (ti.c_lflag & NOFLSH)
diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc
index 953aeade0..383e20764 100644
--- a/winsup/cygwin/fhandler_termios.cc
+++ b/winsup/cygwin/fhandler_termios.cc
@@ -315,12 +315,16 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhandler_termios *fh)
   termios &ti = ttyp->ti;
   pid_t pgid = ttyp->pgid;
 
+  pinfo leader (pgid);
+  bool cyg_leader = leader && !(leader->process_state & PID_NOTCYGWIN);
   bool ctrl_c_event_sent = false;
   bool need_discard_input = false;
   bool pg_with_nat = false;
   bool need_send_sig = false;
   bool nat_shell = false;
   bool cyg_reader = false;
+  bool with_debugger = false;
+  bool with_debugger_nat = false;
 
   winpids pids ((DWORD) 0);
   for (unsigned i = 0; i < pids.npids; i++)
@@ -328,6 +332,7 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhandler_termios *fh)
       _pinfo *p = pids[i];
       if (c == '\003' && p && p->ctty == ttyp->ntty && p->pgid == pgid
 	  && ((p->process_state & PID_NOTCYGWIN)
+	      || (p->process_state & PID_NEW_PG)
 	      || !(p->process_state & PID_CYGPARENT)))
 	{
 	  pinfo pinfo_resume = pinfo (myself->ppid);
@@ -350,7 +355,8 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhandler_termios *fh)
 	  /* CTRL_C_EVENT does not work for the process started with
 	     CREATE_NEW_PROCESS_GROUP flag, so send CTRL_BREAK_EVENT
 	     instead. */
-	  if (p->process_state & PID_NEW_PG)
+	  if ((p->process_state & PID_NEW_PG)
+	      && (p->process_state & PID_NOTCYGWIN))
 	    {
 	      GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT,
 					p->dwProcessId);
@@ -378,8 +384,28 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhandler_termios *fh)
 	    nat_shell = true;
 	  if (p->process_state & PID_TTYIN)
 	    cyg_reader = true;
+	  if (!p->cygstarted && !(p->process_state & PID_NOTCYGWIN)
+	      && (p != myself || being_debugged ())
+	      && cyg_leader) /* inferior is cygwin app */
+	    with_debugger = true;
+	  if (!(p->process_state & PID_NOTCYGWIN)
+	      && (p->process_state & PID_NEW_PG) /* Check marker */
+	      && p->pid == pgid) /* inferior is non-cygwin app */
+	    with_debugger_nat = true;
 	}
     }
+  if ((with_debugger || with_debugger_nat) && need_discard_input)
+    {
+      if (!(ti.c_lflag & NOFLSH) && fh)
+	{
+	  fh->eat_readahead (-1);
+	  fh->discard_input ();
+	}
+      ti.c_lflag &= ~FLUSHO;
+      return done_with_debugger;
+    }
+  if (with_debugger_nat)
+    return not_signalled;
   /* Send SIGQUIT to non-cygwin process. */
   if ((ti.c_lflag & ISIG) && CCEQ (ti.c_cc[VQUIT], c)
       && pg_with_nat && need_send_sig && !nat_shell)
@@ -491,6 +517,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
 	  sawsig = true;
 	  fallthrough;
 	case not_signalled_but_done:
+	case done_with_debugger:
 	  get_ttyp ()->output_stopped = false;
 	  continue;
 	case not_signalled_with_nat_reader:
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index b9549bba9..4aafe08fa 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -2293,7 +2293,14 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 
       for (size_t i = 0; i < nlen; i++)
 	{
-	  fhandler_termios::process_sigs (buf[i], get_ttyp (), this);
+	  process_sig_state r = process_sigs (buf[i], get_ttyp (), this);
+	  if (r == done_with_debugger)
+	    {
+	      for (size_t j = i; j < nlen - 1; j++)
+		buf[j] = buf[j + 1];
+	      nlen--;
+	      i--;
+	    }
 	  process_stop_start (buf[i], get_ttyp (), true);
 	}
 
-- 
2.35.1



More information about the Cygwin-patches mailing list