This is the mail archive of the cygwin-patches mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 1/1] Cygwin: pty: Fix the behaviour of Ctrl-C in the pseudo console mode.


- When the I/O pipe is switched to the pseudo console side, the
  behaviour of Ctrl-C is unstable. This rarely happens, however,
  for example, shell sometimes crashes by Ctrl-C in that situation.
  This patch fixes that issue.
---
 winsup/cygwin/fhandler.h      |   4 +-
 winsup/cygwin/fhandler_tty.cc |  32 +++++----
 winsup/cygwin/select.cc       |   2 +-
 winsup/cygwin/spawn.cc        | 128 +++++++++++++++++-----------------
 4 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index e72e11f7a..1e3cada08 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -2187,9 +2187,9 @@ class fhandler_pty_slave: public fhandler_pty_common
     get_ttyp ()->mask_switch_to_pcon = mask;
   }
   void fixup_after_attach (bool native_maybe);
-  pid_t get_pcon_pid (void)
+  pid_t getpgid (void)
   {
-    return get_ttyp ()->pcon_pid;
+    return get_ttyp ()->getpgid ();
   }
   bool is_line_input (void)
   {
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 2533e5618..150530c5e 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -1018,20 +1018,25 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
       get_ttyp ()->need_clear_screen = false;
     }
 
-  if (ALWAYS_USE_PCON)
-    return;
   if (isHybrid)
-    {
-      this->set_switch_to_pcon ();
-      return;
-    }
+    this->set_switch_to_pcon ();
   if (get_ttyp ()->pcon_pid &&
       get_ttyp ()->pcon_pid != myself->pid &&
       kill (get_ttyp ()->pcon_pid, 0) == 0)
     /* There is a process which is grabbing pseudo console. */
     return;
-  if (get_ttyp ()->switch_to_pcon &&
-      get_ttyp ()->pcon_pid != myself->pid)
+  if (isHybrid)
+    {
+      DWORD mode;
+      GetConsoleMode (get_handle (), &mode);
+      if (ALWAYS_USE_PCON)
+	mode &= ~ENABLE_PROCESSED_INPUT;
+      SetConsoleMode (get_handle (), mode & ~ENABLE_ECHO_INPUT);
+      get_ttyp ()->pcon_pid = 0;
+      init_console_handler (true);
+      return;
+    }
+  if (get_ttyp ()->switch_to_pcon)
     {
       DWORD mode;
       GetConsoleMode (get_handle (), &mode);
@@ -1040,6 +1045,7 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
     }
   get_ttyp ()->pcon_pid = 0;
   get_ttyp ()->switch_to_pcon = false;
+  init_console_handler (true);
 }
 
 void
@@ -1299,8 +1305,7 @@ fhandler_pty_slave::read (void *ptr, size_t& len)
   if (ptr) /* Indicating not tcflush(). */
     {
       reset_switch_to_pcon ();
-      if (get_ttyp ()->pcon_pid != myself->pid)
-	mask_switch_to_pcon (true);
+      mask_switch_to_pcon (true);
     }
 
   if (is_nonblocking () || !ptr) /* Indicating tcflush(). */
@@ -1420,7 +1425,7 @@ fhandler_pty_slave::read (void *ptr, size_t& len)
 	    flags &= ~ENABLE_ECHO_INPUT;
 	  if ((get_ttyp ()->ti.c_lflag & ISIG) &&
 	      !(get_ttyp ()->ti.c_iflag & IGNBRK))
-	    flags |= ENABLE_PROCESSED_INPUT;
+	    flags |= ALWAYS_USE_PCON ? 0 : ENABLE_PROCESSED_INPUT;
 	  if (dwMode != flags)
 	    SetConsoleMode (get_handle (), flags);
 	  /* Read get_handle() instad of get_handle_cyg() */
@@ -2867,8 +2872,10 @@ fhandler_pty_slave::fixup_after_attach (bool native_maybe)
 	      get_ttyp ()->num_pcon_attached_slaves ++;
 	    }
 	}
+      if (ALWAYS_USE_PCON && pcon_attached_to == get_minor ())
+	set_ishybrid_and_switch_to_pcon (get_output_handle ());
     }
-  if (pcon_attached_to == get_minor () && (native_maybe || ALWAYS_USE_PCON))
+  if (pcon_attached_to == get_minor () && native_maybe)
     {
       FlushConsoleInputBuffer (get_handle ());
       DWORD mode;
@@ -2883,6 +2890,7 @@ fhandler_pty_slave::fixup_after_attach (bool native_maybe)
 	  kill (get_ttyp ()->pcon_pid, 0) != 0)
 	get_ttyp ()->pcon_pid = myself->pid;
       get_ttyp ()->switch_to_pcon = true;
+      init_console_handler(false);
     }
 }
 
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 4efc302df..3589ccabf 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -1294,7 +1294,7 @@ pty_slave_startup (select_record *me, select_stuff *stuff)
 {
   fhandler_base *fh = (fhandler_base *) me->fh;
   fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
-  if (me->read_selected && ptys->get_pcon_pid () != myself->pid)
+  if (me->read_selected)
     ptys->mask_switch_to_pcon (true);
 
   select_pipe_info *pi = stuff->device_specific_ptys;
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 15cba3610..2cd43f681 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -262,6 +262,67 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
   DWORD pidRestore = 0;
   bool attach_to_pcon = false;
 
+  /* Attach to pseudo console if pty salve is used */
+  pidRestore = fhandler_console::get_console_process_id
+    (GetCurrentProcessId (), false);
+  fhandler_pty_slave *ptys = NULL;
+  int chk_order[] = {1, 0, 2};
+  for (int i = 0; i < 3; i ++)
+    {
+      int fd = chk_order[i];
+      fhandler_base *fh = ::cygheap->fdtab[fd];
+      if (fh && fh->get_major () == DEV_PTYS_MAJOR)
+	{
+	  ptys = (fhandler_pty_slave *) fh;
+	  if (ptys->getPseudoConsole ())
+	    {
+	      DWORD dwHelperProcessId = ptys->getHelperProcessId ();
+	      debug_printf ("found a PTY slave %d: helper_PID=%d",
+			    fh->get_minor (), dwHelperProcessId);
+	      if (fhandler_console::get_console_process_id
+		  (dwHelperProcessId, true))
+		{
+		  /* Already attached */
+		  attach_to_pcon = true;
+		  break;
+		}
+	      else
+		{
+		  FreeConsole ();
+		  if (AttachConsole (dwHelperProcessId))
+		    {
+		      attach_to_pcon = true;
+		      break;
+		    }
+		  else
+		    {
+		      /* Fallback */
+		      DWORD target[3] = {
+			STD_INPUT_HANDLE,
+			STD_OUTPUT_HANDLE,
+			STD_ERROR_HANDLE
+		      };
+		      if (fd == 0)
+			{
+			  ptys->set_handle (ptys->get_handle_cyg ());
+			  SetStdHandle (target[fd],
+					ptys->get_handle ());
+			}
+		      else if (fd < 3)
+			{
+			  ptys->set_output_handle (
+				       ptys->get_output_handle_cyg ());
+			  SetStdHandle (target[fd],
+					ptys->get_output_handle ());
+			}
+		    }
+		}
+	    }
+	}
+    }
+  if (ptys)
+    ptys->fixup_after_attach (!iscygwin ());
+
   /* Check if we have been called from exec{lv}p or spawn{lv}p and mask
      mode to keep only the spawn mode. */
   bool p_type_exec = !!(mode & _P_PATH_TYPE_EXEC);
@@ -539,8 +600,10 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
 	 in a console will break native processes running in the background,
 	 because the Ctrl-C event is sent to all processes in the console, unless
 	 they ignore it explicitely.  CREATE_NEW_PROCESS_GROUP does that for us. */
-      if (!iscygwin () && fhandler_console::exists ()
-	  && fhandler_console::tc_getpgid () != myself->pgid)
+      if (!iscygwin () &&
+	  ((fhandler_console::exists ()
+		&& fhandler_console::tc_getpgid () != myself->pgid)
+	   || (ptys && ptys->getpgid () != myself->pgid)))
 	c_flags |= CREATE_NEW_PROCESS_GROUP;
       refresh_cygheap ();
 
@@ -574,67 +637,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
 			 PROCESS_QUERY_LIMITED_INFORMATION))
 	sa = &sec_none_nih;
 
-      /* Attach to pseudo console if pty salve is used */
-      pidRestore = fhandler_console::get_console_process_id
-	(GetCurrentProcessId (), false);
-      fhandler_pty_slave *ptys = NULL;
-      int chk_order[] = {1, 0, 2};
-      for (int i = 0; i < 3; i ++)
-	{
-	  int fd = chk_order[i];
-	  fhandler_base *fh = ::cygheap->fdtab[fd];
-	  if (fh && fh->get_major () == DEV_PTYS_MAJOR)
-	    {
-	      ptys = (fhandler_pty_slave *) fh;
-	      if (ptys->getPseudoConsole ())
-		{
-		  DWORD dwHelperProcessId = ptys->getHelperProcessId ();
-		  debug_printf ("found a PTY slave %d: helper_PID=%d",
-				    fh->get_minor (), dwHelperProcessId);
-		  if (fhandler_console::get_console_process_id
-					      (dwHelperProcessId, true))
-		    {
-		      /* Already attached */
-		      attach_to_pcon = true;
-		      break;
-		    }
-		  else
-		    {
-		      FreeConsole ();
-		      if (AttachConsole (dwHelperProcessId))
-			{
-			  attach_to_pcon = true;
-			  break;
-			}
-		      else
-			{
-			  /* Fallback */
-			  DWORD target[3] = {
-			    STD_INPUT_HANDLE,
-			    STD_OUTPUT_HANDLE,
-			    STD_ERROR_HANDLE
-			  };
-			  if (fd == 0)
-			    {
-			      ptys->set_handle (ptys->get_handle_cyg ());
-			      SetStdHandle (target[fd],
-					    ptys->get_handle ());
-			    }
-			  else if (fd < 3)
-			    {
-			      ptys->set_output_handle (
-					   ptys->get_output_handle_cyg ());
-			      SetStdHandle (target[fd],
-					    ptys->get_output_handle ());
-			    }
-			}
-		    }
-		}
-	    }
-	}
-      if (ptys)
-	ptys->fixup_after_attach (!iscygwin ());
-
       if (!iscygwin ())
 	{
 	  init_console_handler (myself->ctty > 0);
-- 
2.21.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]