[newlib-cygwin/cygwin-3_3-branch] Cygwin: console: Redesign handling of special keys.

Takashi Yano tyan0@sourceware.org
Wed Feb 23 17:49:18 GMT 2022


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=018d06f867d750f9118c221d164e52de89b16b7d

commit 018d06f867d750f9118c221d164e52de89b16b7d
Author: Takashi Yano <takashi.yano@nifty.ne.jp>
Date:   Wed Feb 23 13:24:39 2022 +0900

    Cygwin: console: Redesign handling of special keys.
    
    - This patch rearranges the cooperation between cons_master_thread,
      line_edit, and ctrl_c_handler so that only one of them operates
      at the same time. Since these handle Ctrl-C individually, so the
      signal may be sent multiple times to the process. This patch fixes
      the issue.

Diff:
---
 winsup/cygwin/fhandler.h          |  7 +++---
 winsup/cygwin/fhandler_console.cc | 49 ++++++++++++++++++++++++---------------
 winsup/cygwin/fhandler_termios.cc | 29 +++++++++++++----------
 winsup/cygwin/sigproc.cc          |  3 ++-
 4 files changed, 53 insertions(+), 35 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index b6d9d83d4..c2a27f3b7 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1906,7 +1906,7 @@ class fhandler_termios: public fhandler_base
     signalled,
     not_signalled,
     not_signalled_but_done,
-    not_signalled_with_cyg_reader
+    not_signalled_with_nat_reader
   };
 
  public:
@@ -1954,8 +1954,8 @@ class fhandler_termios: public fhandler_base
   }
   static bool path_iscygexec_a (LPCSTR n, LPSTR c);
   static bool path_iscygexec_w (LPCWSTR n, LPWSTR c);
-  virtual bool is_pty_master_with_pcon () { return false; }
   virtual void cleanup_before_exit () {}
+  virtual bool need_console_handler () { return false; }
 };
 
 enum ansi_intensity
@@ -2060,6 +2060,7 @@ class dev_console
   char cons_rabuf[40];  // cannot get longer than char buf[40] in char_command
   char *cons_rapoi;
   bool cursor_key_app_mode;
+  bool disable_master_thread;
 
   inline UINT get_console_cp ();
   DWORD con_to_str (char *d, int dlen, WCHAR w);
@@ -2253,6 +2254,7 @@ private:
   void setup_for_non_cygwin_app ();
   static void cleanup_for_non_cygwin_app (handle_set_t *p);
   static void set_console_mode_to_native ();
+  bool need_console_handler ();
 
   friend tty_min * tty_list::get_cttyp ();
 };
@@ -2488,7 +2490,6 @@ public:
   void get_master_thread_param (master_thread_param_t *p);
   void get_master_fwd_thread_param (master_fwd_thread_param_t *p);
   void set_mask_flusho (bool m) { get_ttyp ()->mask_flusho = m; }
-  bool is_pty_master_with_pcon () { return get_ttyp ()->pcon_activated; }
 };
 
 class fhandler_dev_null: public fhandler_base
diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc
index a099afd2e..f8fe4d1b1 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -195,21 +195,7 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
       DWORD total_read, n, i;
       INPUT_RECORD input_rec[INREC_SIZE];
 
-      bool nat_fg = false;
-      bool nat_child_fg = false;
-      winpids pids ((DWORD) 0);
-      for (unsigned i = 0; i < pids.npids; i++)
-	{
-	  _pinfo *pi = pids[i];
-	  if (pi && pi->ctty == ttyp->ntty && pi->pgid == ttyp->getpgid ()
-	      && (pi->process_state & PID_NOTCYGWIN)
-	      && !(pi->process_state & PID_NEW_PG))
-	    nat_fg = true;
-	  if (pi && pi->ctty == ttyp->ntty && pi->pgid == ttyp->getpgid ()
-	      && !(pi->process_state & PID_CYGPARENT))
-	    nat_child_fg = true;
-	}
-      if (nat_fg && !nat_child_fg)
+      if (con.disable_master_thread)
 	{
 	  cygwait (40);
 	  continue;
@@ -402,6 +388,7 @@ fhandler_console::setup ()
       con.cons_rapoi = NULL;
       shared_console_info->tty_min_state.is_console = true;
       con.cursor_key_app_mode = false;
+      con.disable_master_thread = true;
     }
 }
 
@@ -518,6 +505,7 @@ fhandler_console::setup_for_non_cygwin_app ()
     (get_ttyp ()->getpgid ()== myself->pgid) ? tty::native : tty::restore;
   set_input_mode (conmode, &tc ()->ti, get_handle_set ());
   set_output_mode (conmode, &tc ()->ti, get_handle_set ());
+  con.disable_master_thread = true;
 }
 
 void
@@ -533,6 +521,7 @@ fhandler_console::cleanup_for_non_cygwin_app (handle_set_t *p)
     (con.owner == myself->pid) ? tty::restore : tty::cygwin;
   set_output_mode (conmode, ti, p);
   set_input_mode (conmode, ti, p);
+  con.disable_master_thread = (con.owner == myself->pid);
 }
 
 /* Return the tty structure associated with a given tty number.  If the
@@ -705,7 +694,14 @@ fhandler_console::bg_check (int sig, bool dontsignal)
      cygwin app and other non-cygwin apps are started simultaneously
      in the same process group. */
   if (sig == SIGTTIN)
-    set_input_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
+    {
+      set_input_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
+      if (con.disable_master_thread)
+	{
+	  con.disable_master_thread = false;
+	  init_console_handler (false);
+	}
+    }
   if (sig == SIGTTOU)
     set_output_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
 
@@ -1407,8 +1403,7 @@ bool
 fhandler_console::open_setup (int flags)
 {
   set_flags ((flags & ~O_TEXT) | O_BINARY);
-  if (myself->set_ctty (this, flags) && !myself->cygstarted)
-    init_console_handler (true);
+  myself->set_ctty (this, flags);
   return fhandler_base::open_setup (flags);
 }
 
@@ -1417,10 +1412,15 @@ fhandler_console::post_open_setup (int fd)
 {
   /* Setting-up console mode for cygwin app started from non-cygwin app. */
   if (fd == 0)
-    set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
+    {
+      set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
+      con.disable_master_thread = false;
+    }
   else if (fd == 1 || fd == 2)
     set_output_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
 
+  init_console_handler (need_console_handler ());
+
   fhandler_base::post_open_setup (fd);
 }
 
@@ -1444,6 +1444,7 @@ fhandler_console::close ()
 	  /* Cleaning-up console mode for cygwin apps. */
 	  set_output_mode (tty::restore, &get_ttyp ()->ti, &handle_set);
 	  set_input_mode (tty::restore, &get_ttyp ()->ti, &handle_set);
+	  con.disable_master_thread = true;
 	}
     }
 
@@ -3615,6 +3616,7 @@ fhandler_console::set_console_mode_to_native ()
 	    termios *cons_ti = &cons->tc ()->ti;
 	    set_input_mode (tty::native, cons_ti, cons->get_handle_set ());
 	    set_output_mode (tty::native, cons_ti, cons->get_handle_set ());
+	    con.disable_master_thread = true;
 	    break;
 	  }
       }
@@ -3637,6 +3639,7 @@ CreateProcessA_Hooked
   gdb_inferior_noncygwin = !fhandler_termios::path_iscygexec_a (n, c);
   if (gdb_inferior_noncygwin)
     fhandler_console::set_console_mode_to_native ();
+  init_console_handler (false);
   return CreateProcessA_Orig (n, c, pa, ta, inh, f, e, d, si, pi);
 }
 
@@ -3651,6 +3654,7 @@ CreateProcessW_Hooked
   gdb_inferior_noncygwin = !fhandler_termios::path_iscygexec_w (n, c);
   if (gdb_inferior_noncygwin)
     fhandler_console::set_console_mode_to_native ();
+  init_console_handler (false);
   return CreateProcessW_Orig (n, c, pa, ta, inh, f, e, d, si, pi);
 }
 
@@ -3660,6 +3664,7 @@ ContinueDebugEvent_Hooked
 {
   if (gdb_inferior_noncygwin)
     fhandler_console::set_console_mode_to_native ();
+  init_console_handler (false);
   return ContinueDebugEvent_Orig (p, t, s);
 }
 
@@ -3957,3 +3962,9 @@ fhandler_console::close_handle_set (handle_set_t *p)
   CloseHandle (p->output_mutex);
   p->output_mutex = NULL;
 }
+
+bool
+fhandler_console::need_console_handler ()
+{
+  return con.disable_master_thread;
+}
diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc
index 46c861928..953aeade0 100644
--- a/winsup/cygwin/fhandler_termios.cc
+++ b/winsup/cygwin/fhandler_termios.cc
@@ -315,8 +315,6 @@ 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;
@@ -344,24 +342,31 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhandler_termios *fh)
 	      FreeConsole ();
 	      AttachConsole (p->dwProcessId);
 	    }
+	  if (fh && p == myself)
+	    { /* Avoid deadlock in gdb on console. */
+	      fh->tcflush(TCIFLUSH);
+	      fh->release_input_mutex_if_necessary ();
+	    }
 	  /* 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)
-	    GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT,
-				      p->dwProcessId);
-	  else if ((!fh || !fh->is_pty_master_with_pcon () || cyg_leader)
-		   && !ctrl_c_event_sent)
+	    {
+	      GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT,
+					p->dwProcessId);
+	      need_discard_input = true;
+	    }
+	  else if (!ctrl_c_event_sent)
 	    {
 	      GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0);
 	      ctrl_c_event_sent = true;
+	      need_discard_input = true;
 	    }
 	  if (resume_pid && fh && !fh->is_console ())
 	    {
 	      FreeConsole ();
 	      AttachConsole (resume_pid);
 	    }
-	  need_discard_input = true;
 	}
       if (p && p->ctty == ttyp->ntty && p->pgid == pgid)
 	{
@@ -426,8 +431,8 @@ not_a_sig:
       ti.c_lflag &= ~FLUSHO;
       return not_signalled_but_done;
     }
-  bool to_cyg = cyg_reader || !pg_with_nat;
-  return to_cyg ? not_signalled_with_cyg_reader : not_signalled;
+  bool to_nat = !cyg_reader && pg_with_nat;
+  return to_nat ? not_signalled_with_nat_reader : not_signalled;
 }
 
 bool
@@ -479,7 +484,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
 
       if (ti.c_iflag & ISTRIP)
 	c &= 0x7f;
-      bool disable_eof_key = true;
+      bool disable_eof_key = false;
       switch (process_sigs (c, get_ttyp (), this))
 	{
 	case signalled:
@@ -488,8 +493,8 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
 	case not_signalled_but_done:
 	  get_ttyp ()->output_stopped = false;
 	  continue;
-	case not_signalled_with_cyg_reader:
-	  disable_eof_key = false;
+	case not_signalled_with_nat_reader:
+	  disable_eof_key = true;
 	  break;
 	default: /* Not signalled */
 	  break;
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 02d875a7f..26dba9096 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -1412,7 +1412,8 @@ wait_sig (VOID *)
 	  sig_held = true;
 	  break;
 	case __SIGSETPGRP:
-	  init_console_handler (true);
+	  if (::cygheap->ctty)
+	    init_console_handler (::cygheap->ctty->need_console_handler ());
 	  break;
 	case __SIGTHREADEXIT:
 	  {


More information about the Cygwin-cvs mailing list