public inbox for cygwin-developers@cygwin.com
 help / color / mirror / Atom feed
From: Takashi Yano <takashi.yano@nifty.ne.jp>
To: cygwin-developers@cygwin.com
Subject: Re: New implementation of pseudo console support (experimental)
Date: Fri, 29 May 2020 00:40:24 +0900	[thread overview]
Message-ID: <20200529004024.0c2ac3c68b588bda987e0837@nifty.ne.jp> (raw)
In-Reply-To: <20200526100955.30b1a2baea517e0565f30db6@nifty.ne.jp>

[-- Attachment #1: Type: text/plain, Size: 1064 bytes --]

On Tue, 26 May 2020 10:09:55 +0900
Takashi Yano via Cygwin-developers <cygwin-developers@cygwin.com> wrote:
> On Mon, 25 May 2020 19:53:32 +0900
> Takashi Yano via Cygwin-developers <cygwin-developers@cygwin.com> wrote:
> > On Tue, 19 May 2020 22:40:18 +0900
> > Takashi Yano via Cygwin-developers <cygwin-developers@cygwin.com> wrote:
> > > On Sat, 16 May 2020 16:47:35 +0900
> > > Takashi Yano via Cygwin-developers <cygwin-developers@cygwin.com> wrote:
> > > > On Sat, 16 May 2020 09:29:56 +0900
> > > > Takashi Yano via Cygwin-developers <cygwin-developers@cygwin.com> wrote:
> > > > > Fix a small bug caused when stdio is redirected to another pty.
> > > > 
> > > > Fix another bug caused when stdio is redirected to another pty.
> > > 
> > > Revise the patch to fit the current git head.
> > 
> > Revise the patch again to fit the current git head.
> 
> Make app, which reads stdin, work under gdb.

* Prevent ResizePseudoConsole() calls unless the pty is resized.
* Revise the patch to fit the current git head.

-- 
Takashi Yano <takashi.yano@nifty.ne.jp>

[-- Attachment #2: pcon2-20200528.diff --]
[-- Type: text/plain, Size: 20327 bytes --]

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 76ad2aab0..7006aa060 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -2264,6 +2264,7 @@ class fhandler_pty_common: public fhandler_termios
     return get_ttyp ()->h_pseudo_console;
   }
   bool to_be_read_from_pcon (void);
+  void resize_pseudo_console2 (struct winsize *);
 
  protected:
   BOOL process_opost_output (HANDLE h,
@@ -2356,6 +2357,9 @@ class fhandler_pty_slave: public fhandler_pty_common
   void wait_pcon_fwd (void);
   void pull_pcon_input (void);
   void update_pcon_input_state (bool need_lock);
+  bool setup_pseudoconsole2 (STARTUPINFOEXW *si);
+  void close_pseudoconsole2 (void);
+  void wait_pcon_fwd2 (void);
 };
 
 #define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit))
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index b091765b3..6c042409a 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -41,6 +41,8 @@ extern "C" {
   VOID WINAPI ClosePseudoConsole (HPCON);
 }
 
+#define USE_PCON_MODE2 true
+
 #define close_maybe(h) \
   do { \
     if (h && h != INVALID_HANDLE_VALUE) \
@@ -73,7 +75,7 @@ clear_pcon_attached_to (void)
 }
 
 static void
-set_switch_to_pcon (void)
+set_switch_to_pcon (HANDLE h)
 {
   cygheap_fdenum cfd (false);
   int fd;
@@ -90,6 +92,8 @@ set_switch_to_pcon (void)
 	      ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT;
 	    SetConsoleMode (ptys->get_handle (), mode);
 	  }
+	else if (USE_PCON_MODE2 && h == ptys->get_handle ())
+	  ptys->set_switch_to_pcon (fd);
 	return;
       }
   /* No pty slave opened */
@@ -180,7 +184,7 @@ set_ishybrid_and_switch_to_pcon (HANDLE h)
 			|| GetLastError () != ERROR_INVALID_HANDLE))
 	{
 	  isHybrid = true;
-	  set_switch_to_pcon ();
+	  set_switch_to_pcon (h);
 	}
     }
 }
@@ -363,11 +367,25 @@ CreateProcessA_Hooked
       LPSTARTUPINFOA si, LPPROCESS_INFORMATION pi)
 {
   HANDLE h;
-  if (si->dwFlags & STARTF_USESTDHANDLES)
-    h = si->hStdOutput;
+  if (USE_PCON_MODE2)
+    {
+      if (!isHybrid)
+	{
+	  if (si->dwFlags & STARTF_USESTDHANDLES)
+	    h = si->hStdInput;
+	  else
+	    h = GetStdHandle (STD_INPUT_HANDLE);
+	  set_switch_to_pcon (h);
+	}
+    }
   else
-    h = GetStdHandle (STD_OUTPUT_HANDLE);
-  set_ishybrid_and_switch_to_pcon (h);
+    {
+      if (si->dwFlags & STARTF_USESTDHANDLES)
+	h = si->hStdOutput;
+      else
+	h = GetStdHandle (STD_OUTPUT_HANDLE);
+      set_ishybrid_and_switch_to_pcon (h);
+    }
   return CreateProcessA_Orig (n, c, pa, ta, inh, f, e, d, si, pi);
 }
 static BOOL WINAPI
@@ -377,11 +395,25 @@ CreateProcessW_Hooked
       LPSTARTUPINFOW si, LPPROCESS_INFORMATION pi)
 {
   HANDLE h;
-  if (si->dwFlags & STARTF_USESTDHANDLES)
-    h = si->hStdOutput;
+  if (USE_PCON_MODE2)
+    {
+      if (!isHybrid)
+	{
+	  if (si->dwFlags & STARTF_USESTDHANDLES)
+	    h = si->hStdInput;
+	  else
+	    h = GetStdHandle (STD_INPUT_HANDLE);
+	  set_switch_to_pcon (h);
+	}
+    }
   else
-    h = GetStdHandle (STD_OUTPUT_HANDLE);
-  set_ishybrid_and_switch_to_pcon (h);
+    {
+      if (si->dwFlags & STARTF_USESTDHANDLES)
+	h = si->hStdOutput;
+      else
+	h = GetStdHandle (STD_OUTPUT_HANDLE);
+      set_ishybrid_and_switch_to_pcon (h);
+    }
   return CreateProcessW_Orig (n, c, pa, ta, inh, f, e, d, si, pi);
 }
 
@@ -542,22 +574,26 @@ fhandler_pty_master::accept_input ()
 
   bytes_left = eat_readahead (-1);
 
+  HANDLE write_to = get_output_handle ();
+  if (to_be_read_from_pcon () && USE_PCON_MODE2)
+    write_to = to_slave;
+
   if (!bytes_left)
     {
       termios_printf ("sending EOF to slave");
       get_ttyp ()->read_retval = 0;
     }
-  else if (!to_be_read_from_pcon ())
+  else if (!to_be_read_from_pcon () || USE_PCON_MODE2)
     {
       char *p = rabuf ();
       DWORD rc;
       DWORD written = 0;
 
       paranoid_printf ("about to write %u chars to slave", bytes_left);
-      rc = WriteFile (get_output_handle (), p, bytes_left, &written, NULL);
+      rc = WriteFile (write_to, p, bytes_left, &written, NULL);
       if (!rc)
 	{
-	  debug_printf ("error writing to pipe %p %E", get_output_handle ());
+	  debug_printf ("error writing to pipe %p %E", write_to);
 	  get_ttyp ()->read_retval = -1;
 	  ret = -1;
 	}
@@ -1267,6 +1303,18 @@ fhandler_pty_slave::set_switch_to_pcon (int fd_set)
 {
   if (fd < 0)
     fd = fd_set;
+  if (USE_PCON_MODE2)
+    {
+      if (!get_ttyp ()->switch_to_pcon_in)
+	{
+	  isHybrid = true;
+	  if (get_ttyp ()->pcon_pid == 0 ||
+	      !pinfo (get_ttyp ()->pcon_pid))
+	    get_ttyp ()->pcon_pid = myself->pid;
+	  get_ttyp ()->switch_to_pcon_in = true;
+	}
+      return;
+    }
   if (fd == 0 && !get_ttyp ()->switch_to_pcon_in)
     {
       pull_pcon_input ();
@@ -1311,6 +1359,7 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
   get_ttyp ()->switch_to_pcon_in = false;
   get_ttyp ()->switch_to_pcon_out = false;
   init_console_handler (true);
+  get_ttyp ()->h_pseudo_console2 = NULL;
 }
 
 void
@@ -1570,8 +1619,9 @@ fhandler_pty_slave::mask_switch_to_pcon_in (bool mask)
 bool
 fhandler_pty_common::to_be_read_from_pcon (void)
 {
-  return !get_ttyp ()->pcon_in_empty ||
-    (get_ttyp ()->switch_to_pcon_in && !get_ttyp ()->mask_switch_to_pcon_in);
+  return !get_ttyp ()->pcon_in_empty || get_ttyp ()->pcon2_start
+    || (get_ttyp ()->switch_to_pcon_in
+	&& !get_ttyp ()->mask_switch_to_pcon_in);
 }
 
 void __reg3
@@ -2079,6 +2129,8 @@ cleanup:
       if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
 	  || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
 	{
+	  if (get_ttyp ()->h_pseudo_console2 && get_ttyp ()->pcon_pid)
+	    resize_pseudo_console2 ((struct winsize *) arg);
 	  get_ttyp ()->arg.winsize = *(struct winsize *) arg;
 	  get_ttyp ()->winsize = *(struct winsize *) arg;
 	  get_ttyp ()->kill_pgrp (SIGWINCH);
@@ -2364,6 +2416,27 @@ fhandler_pty_common::close ()
   return 0;
 }
 
+void
+fhandler_pty_common::resize_pseudo_console2 (struct winsize *ws)
+{
+  COORD size;
+  size.X = ws->ws_col;
+  size.Y = ws->ws_row;
+  pinfo p (get_ttyp ()->pcon_pid);
+  if (p)
+    {
+      HPCON_INTERNAL hpcon_local;
+      HANDLE pcon_owner =
+	OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->exec_dwProcessId);
+      DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_write_pipe,
+		       GetCurrentProcess (), &hpcon_local.hWritePipe,
+		       0, TRUE, DUPLICATE_SAME_ACCESS);
+      ResizePseudoConsole ((HPCON) &hpcon_local, size);
+      CloseHandle (pcon_owner);
+      CloseHandle (hpcon_local.hWritePipe);
+    }
+}
+
 void
 fhandler_pty_master::cleanup ()
 {
@@ -2501,7 +2574,8 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 
   /* Write terminal input to to_slave pipe instead of output_handle
      if current application is native console application. */
-  if (to_be_read_from_pcon ())
+  if (to_be_read_from_pcon ()
+      && (!USE_PCON_MODE2 || get_ttyp ()->h_pseudo_console2))
     {
       size_t nlen;
       char *buf = convert_mb_str
@@ -2513,11 +2587,52 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 	get_ttyp ()->req_flush_pcon_input = true;
 
       DWORD wLen;
+
+      if (get_ttyp ()->pcon2_start)
+	{
+	  /* Pseudo condole support mode-2 uses "CSI6n" to get cursor
+	     position. If the reply for "CSI6n" is divided into multiple
+	     writes, pseudo console sometimes does not recognize it.
+	     Therefore, put them together into wpbuf and write all at once. */
+	  static const int wpbuf_len = 64;
+	  static char wpbuf[wpbuf_len];
+	  static int ixput = 0;
+
+	  if (ixput == 0 && buf[0] != '\033')
+	    { /* fail-safe */
+	      WriteFile (to_slave, "\033[1;1R", 6, &wLen, NULL); /* dummy */
+	      get_ttyp ()->pcon2_start = false;
+	    }
+	  else
+	    {
+	      if (ixput + nlen < wpbuf_len)
+		for (size_t i=0; i<nlen; i++)
+		  wpbuf[ixput++] = buf[i];
+	      else
+		{
+		  WriteFile (to_slave, wpbuf, ixput, &wLen, NULL);
+		  ixput = 0;
+		  get_ttyp ()->pcon2_start = false;
+		  WriteFile (to_slave, buf, nlen, &wLen, NULL);
+		}
+	      if (ixput && memchr (wpbuf, 'R', ixput))
+		{
+		  WriteFile (to_slave, wpbuf, ixput, &wLen, NULL);
+		  ixput = 0;
+		  get_ttyp ()->pcon2_start = false;
+		}
+	      ReleaseMutex (input_mutex);
+	      mb_str_free (buf);
+	      return len;
+	    }
+	}
+
       WriteFile (to_slave, buf, nlen, &wLen, NULL);
       get_ttyp ()->pcon_in_empty = false;
 
       ReleaseMutex (input_mutex);
 
+#if !USE_PCON_MODE2
       /* Use line_edit () in order to set input_available_event. */
       bool is_echo = tc ()->ti.c_lflag & ECHO;
       if (!get_ttyp ()->mask_switch_to_pcon_in)
@@ -2543,6 +2658,7 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 	      eat_readahead (-1);
 	      SetEvent (input_available_event);
 	    }
+#endif /* USE_PCON_MODE2 */
 
       mb_str_free (buf);
       return len;
@@ -2627,6 +2743,8 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
 	      size.Y = ((struct winsize *) arg)->ws_row;
 	      ResizePseudoConsole (get_pseudo_console (), size);
 	    }
+	  if (get_ttyp ()->h_pseudo_console2 && get_ttyp ()->pcon_pid)
+	    resize_pseudo_console2 ((struct winsize *) arg);
 	  get_ttyp ()->winsize = *(struct winsize *) arg;
 	  get_ttyp ()->kill_pgrp (SIGWINCH);
 	}
@@ -2901,6 +3019,12 @@ fhandler_pty_slave::wait_pcon_fwd (void)
 	 && cygwait (get_ttyp ()->fwd_done, 1) == WAIT_TIMEOUT);
 }
 
+void
+fhandler_pty_slave::wait_pcon_fwd2 (void)
+{
+  get_ttyp ()->wait_pcon_fwd ();
+}
+
 void
 fhandler_pty_slave::trigger_redraw_screen (void)
 {
@@ -3054,6 +3178,12 @@ fhandler_pty_slave::fixup_after_exec ()
       DO_HOOK (NULL, CreateProcessA);
       DO_HOOK (NULL, CreateProcessW);
     }
+  if (USE_PCON_MODE2)
+    {
+      /* CreateProcess() is hooked for GDB etc. */
+      DO_HOOK (NULL, CreateProcessA);
+      DO_HOOK (NULL, CreateProcessW);
+    }
 }
 
 /* This thread function handles the master control pipe.  It waits for a
@@ -3270,6 +3400,8 @@ fhandler_pty_master::pty_master_fwd_thread ()
 	      Sleep (1);
 	    }
 	}
+      if (USE_PCON_MODE2)
+	get_ttyp ()->pcon_last_time = GetTickCount ();
       if (!ReadFile (from_slave, outbuf, sizeof outbuf, &rlen, NULL))
 	{
 	  termios_printf ("ReadFile for forwarding failed, %E");
@@ -3277,8 +3409,9 @@ fhandler_pty_master::pty_master_fwd_thread ()
 	}
       ssize_t wlen = rlen;
       char *ptr = outbuf;
-      if (get_pseudo_console ())
+      if (get_pseudo_console () || get_ttyp ()->h_pseudo_console2)
 	{
+#if !USE_PCON_MODE2
 	  /* Avoid duplicating slave output which is already sent to
 	     to_master_cyg */
 	  if (!get_ttyp ()->switch_to_pcon_out)
@@ -3331,6 +3464,7 @@ fhandler_pty_master::pty_master_fwd_thread ()
 	      rlen -= 4;
 	    }
 	  wlen = rlen;
+#endif /* USE_PCON_MODE2 */
 
 	  size_t nlen;
 	  char *buf = convert_mb_str
@@ -3700,7 +3834,19 @@ fhandler_pty_master::setup ()
   t.winsize.ws_col = 80;
   t.winsize.ws_row = 25;
 
-  setup_pseudoconsole ();
+  if (!USE_PCON_MODE2)
+    setup_pseudoconsole ();
+  else
+    {
+      __small_sprintf (pipename, "pty%d-to-slave", unit);
+      res = fhandler_pipe::create (&sec_none, &from_master, &to_slave,
+				   fhandler_pty_common::pipesize, pipename, 0);
+      if (res)
+	{
+	  errstr = "input pipe";
+	  goto err;
+	}
+    }
 
   t.set_from_master (from_master);
   t.set_from_master_cyg (from_master_cyg);
@@ -3718,6 +3864,7 @@ fhandler_pty_master::setup ()
 err:
   __seterrno ();
   close_maybe (from_slave);
+  close_maybe (to_slave);
   close_maybe (get_handle ());
   close_maybe (get_output_handle ());
   close_maybe (input_available_event);
@@ -3862,3 +4009,126 @@ fhandler_pty_common::process_opost_output (HANDLE h, const void *ptr, ssize_t& l
   len -= towrite;
   return res;
 }
+
+bool
+fhandler_pty_slave::setup_pseudoconsole2 (STARTUPINFOEXW *si)
+{
+  if (USE_PCON_MODE2)
+    {
+      fhandler_base *fh = (fhandler_pty_slave *) ::cygheap->fdtab[0];
+      if (fh && fh->get_major () == DEV_PTYS_MAJOR)
+	{
+	  fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
+	  ptys->get_ttyp ()->switch_to_pcon_in = true;
+	  if (ptys->get_ttyp ()->pcon_pid == 0 ||
+	      !pinfo (ptys->get_ttyp ()->pcon_pid))
+	    ptys->get_ttyp ()->pcon_pid = myself->pid;
+	}
+    }
+  if (!USE_PCON_MODE2)
+    return false;
+  if (disable_pcon)
+    return false;
+  /* If the legacy console mode is enabled, pseudo console seems
+     not to work as expected. To determine console mode, registry
+     key ForceV2 in HKEY_CURRENT_USER\Console is checked. */
+  reg_key reg (HKEY_CURRENT_USER, KEY_READ, L"Console", NULL);
+  if (reg.error ())
+    return false;
+  if (reg.get_dword (L"ForceV2", 1) == 0)
+    {
+      termios_printf ("Pseudo console is disabled "
+		      "because the legacy console mode is enabled.");
+      return false;
+    }
+
+  COORD size = {
+    (SHORT) get_ttyp ()->winsize.ws_col,
+    (SHORT) get_ttyp ()->winsize.ws_row
+  };
+  SetLastError (ERROR_SUCCESS);
+  HRESULT res = CreatePseudoConsole (size, get_handle (), get_output_handle (),
+				     1, &get_ttyp ()->h_pseudo_console2);
+  if (res != S_OK || GetLastError () == ERROR_PROC_NOT_FOUND)
+    {
+      if (res != S_OK)
+	system_printf ("CreatePseudoConsole() failed. %08x %08x\n",
+		       GetLastError (), res);
+      goto fallback;
+    }
+
+  SIZE_T bytesRequired;
+  InitializeProcThreadAttributeList (NULL, 1, 0, &bytesRequired);
+  ZeroMemory (si, sizeof (*si));
+  si->StartupInfo.cb = sizeof (STARTUPINFOEXW);
+  si->lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)
+    HeapAlloc (GetProcessHeap (), 0, bytesRequired);
+  if (si->lpAttributeList == NULL)
+    goto cleanup_pseudo_console;
+  if (!InitializeProcThreadAttributeList (si->lpAttributeList,
+					  1, 0, &bytesRequired))
+    goto cleanup_heap;
+  if (!UpdateProcThreadAttribute (si->lpAttributeList,
+				  0,
+				  PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
+				  get_ttyp ()->h_pseudo_console2,
+				  sizeof (get_ttyp ()->h_pseudo_console2),
+				  NULL, NULL))
+    goto cleanup_heap;
+  si->StartupInfo.dwFlags = STARTF_USESTDHANDLES;
+  si->StartupInfo.hStdInput = NULL;
+  si->StartupInfo.hStdOutput = NULL;
+  si->StartupInfo.hStdError = NULL;
+
+  {
+    fhandler_pty_slave *p0 = (fhandler_pty_slave *) ::cygheap->fdtab[0];
+    if (p0 && p0->get_device () != get_device ())
+      si->StartupInfo.hStdInput = p0->get_handle ();
+    fhandler_pty_slave *p1 = (fhandler_pty_slave *) ::cygheap->fdtab[1];
+    if (p1 && p1->get_device () != get_device ())
+      si->StartupInfo.hStdOutput = p1->get_output_handle ();
+    fhandler_pty_slave *p2 = (fhandler_pty_slave *) ::cygheap->fdtab[2];
+    if (p2 && p2->get_device () != get_device ())
+      si->StartupInfo.hStdError = p2->get_output_handle ();
+  }
+
+  if (get_ttyp ()->pcon_pid == 0 || !pinfo (get_ttyp ()->pcon_pid))
+    get_ttyp ()->pcon_pid = myself->pid;
+
+  if (get_ttyp ()->h_pseudo_console2 && get_ttyp ()->pcon_pid == myself->pid)
+    {
+      HPCON_INTERNAL *hp = (HPCON_INTERNAL *) get_ttyp ()->h_pseudo_console2;
+      get_ttyp ()->h_pcon_write_pipe = hp->hWritePipe;
+    }
+  get_ttyp ()->pcon2_start = true;
+  return true;
+
+cleanup_heap:
+  HeapFree (GetProcessHeap (), 0, si->lpAttributeList);
+cleanup_pseudo_console:
+  if (get_ttyp ()->h_pseudo_console2)
+    {
+      HPCON_INTERNAL *hp = (HPCON_INTERNAL *) get_ttyp ()->h_pseudo_console2;
+      HANDLE tmp = hp->hConHostProcess;
+      ClosePseudoConsole (get_ttyp ()->h_pseudo_console2);
+      CloseHandle (tmp);
+    }
+fallback:
+  get_ttyp ()->h_pseudo_console2 = NULL;
+  return false;
+}
+
+void
+fhandler_pty_slave::close_pseudoconsole2 (void)
+{
+  if (get_ttyp ()->h_pseudo_console2)
+    {
+      HPCON_INTERNAL *hp = (HPCON_INTERNAL *) get_ttyp ()->h_pseudo_console2;
+      HANDLE tmp = hp->hConHostProcess;
+      ClosePseudoConsole (get_ttyp ()->h_pseudo_console2);
+      CloseHandle (tmp);
+      get_ttyp ()->h_pseudo_console2 = NULL;
+      get_ttyp ()->switch_to_pcon_in = false;
+      get_ttyp ()->pcon_pid = 0;
+    }
+}
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 3e8c8367a..514125072 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -194,6 +194,24 @@ handle (int fd, bool writing)
   return h;
 }
 
+static bool
+is_console_app (WCHAR *filename)
+{
+  HANDLE h;
+  const int id_offset = 92;
+  h = CreateFileW (filename, GENERIC_READ, FILE_SHARE_READ,
+		  NULL, OPEN_EXISTING, 0, NULL);
+  char buf[1024];
+  DWORD n;
+  ReadFile (h, buf, sizeof (buf), &n, 0);
+  CloseHandle (h);
+  char *p = (char *) memmem (buf, n, "PE\0\0", 4);
+  if (p && p + id_offset <= buf + n)
+    return p[id_offset] == '\003'; /* 02: GUI, 03: console */
+  else
+    return false;
+}
+
 int
 iscmd (const char *argv0, const char *what)
 {
@@ -583,6 +601,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
       /* Attach to pseudo console if pty salve is used */
       pid_restore = fhandler_console::get_console_process_id
 	(GetCurrentProcessId (), false);
+      fhandler_pty_slave *ptys_primary = NULL;
       for (int i = 0; i < 3; i ++)
 	{
 	  const int chk_order[] = {1, 0, 2};
@@ -591,6 +610,8 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
 	  if (fh && fh->get_major () == DEV_PTYS_MAJOR)
 	    {
 	      fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
+	      if (ptys_primary == NULL)
+		ptys_primary = ptys;
 	      if (ptys->get_pseudo_console ())
 		{
 		  DWORD helper_process_id = ptys->get_helper_process_id ();
@@ -632,6 +653,18 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
       if (!iscygwin ())
 	init_console_handler (myself->ctty > 0);
 
+      bool use_pcon_mode2 = false;
+      STARTUPINFOEXW si_pcon;
+      ZeroMemory (&si_pcon, sizeof (si_pcon));
+      STARTUPINFOW *si_tmp = &si;
+      if (!iscygwin () && ptys_primary && is_console_app (runpath))
+	if (ptys_primary->setup_pseudoconsole2 (&si_pcon))
+	  {
+	    c_flags |= EXTENDED_STARTUPINFO_PRESENT;
+	    si_tmp = &si_pcon.StartupInfo;
+	    use_pcon_mode2 = true;
+	  }
+
     loop:
       /* When ruid != euid we create the new process under the current original
 	 account and impersonate in child, this way maintaining the different
@@ -660,7 +693,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
 			       c_flags,
 			       envblock,	/* environment */
 			       NULL,
-			       &si,
+			       si_tmp,
 			       &pi);
 	}
       else
@@ -714,7 +747,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
 			       c_flags,
 			       envblock,	/* environment */
 			       NULL,
-			       &si,
+			       si_tmp,
 			       &pi);
 	  if (hwst)
 	    {
@@ -727,6 +760,11 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
 	      CloseDesktop (hdsk);
 	    }
 	}
+      if (use_pcon_mode2)
+	{
+	  DeleteProcThreadAttributeList (si_pcon.lpAttributeList);
+	  HeapFree (GetProcessHeap (), 0, si_pcon.lpAttributeList);
+	}
 
       if (mode != _P_OVERLAY)
 	SetHandleInformation (my_wr_proc_pipe, HANDLE_FLAG_INHERIT,
@@ -897,6 +935,12 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
 		  && WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT)
 		wait_for_myself ();
 	    }
+	  if (use_pcon_mode2)
+	    {
+	      WaitForSingleObject (pi.hProcess, INFINITE);
+	      ptys_primary->wait_pcon_fwd2 ();
+	      ptys_primary->close_pseudoconsole2 ();
+	    }
 	  myself.exit (EXITCODE_NOSET);
 	  break;
 	case _P_WAIT:
diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
index efdae4697..28316ba6a 100644
--- a/winsup/cygwin/tty.cc
+++ b/winsup/cygwin/tty.cc
@@ -249,6 +249,8 @@ tty::init ()
   pcon_in_empty = true;
   req_transfer_input_to_pcon = false;
   req_flush_pcon_input = false;
+  h_pseudo_console2 = NULL;
+  pcon2_start = false;
 }
 
 HANDLE
diff --git a/winsup/cygwin/tty.h b/winsup/cygwin/tty.h
index 7d6fc8fef..52f3872e2 100644
--- a/winsup/cygwin/tty.h
+++ b/winsup/cygwin/tty.h
@@ -110,6 +110,9 @@ private:
   bool pcon_in_empty;
   bool req_transfer_input_to_pcon;
   bool req_flush_pcon_input;
+  HPCON h_pseudo_console2;
+  HANDLE h_pcon_write_pipe;
+  bool pcon2_start;
 
 public:
   HANDLE from_master () const { return _from_master; }

  reply	other threads:[~2020-05-28 15:40 UTC|newest]

Thread overview: 73+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-13 12:16 Takashi Yano
2020-05-13 12:35 ` Thomas Wolff
2020-05-14  9:28 ` Takashi Yano
2020-05-14  9:34   ` Takashi Yano
2020-05-16  0:29     ` Takashi Yano
2020-05-16  7:47       ` Takashi Yano
2020-05-19 13:40         ` Takashi Yano
2020-05-25 10:53           ` Takashi Yano
2020-05-25 15:22             ` Corinna Vinschen
2020-05-25 19:16               ` Thomas Wolff
2020-05-26  1:00               ` Takashi Yano
2020-05-26  7:14                 ` Thomas Wolff
2020-05-26  9:21                   ` Takashi Yano
2020-05-26  9:32                     ` Thomas Wolff
2020-05-26  8:33                 ` Corinna Vinschen
2020-05-26  1:09             ` Takashi Yano
2020-05-28 15:40               ` Takashi Yano [this message]
2020-05-29 15:30                 ` Corinna Vinschen
2020-05-30  7:36                   ` Takashi Yano
2020-05-30 13:14                     ` Takashi Yano
2020-05-30 17:43                       ` Corinna Vinschen
2020-05-31  5:52                         ` Takashi Yano
2020-07-01 11:47                 ` Takashi Yano
2020-07-17 11:19                   ` Corinna Vinschen
2020-07-17 12:47                     ` Thomas Wolff
2020-07-17 14:59                       ` Thomas Wolff
2020-07-18  5:05                         ` Takashi Yano
2020-07-18 20:57                           ` Thomas Wolff
2020-07-23 17:17                             ` Takashi Yano
2020-07-27 17:10                               ` Thomas Wolff
2020-07-17 12:52                     ` Ken Brown
2020-07-18  5:07                       ` Takashi Yano
2020-07-18  5:30                     ` Takashi Yano
2020-07-20  8:06                       ` Corinna Vinschen
2020-07-21 18:17                         ` Takashi Yano
2020-07-22  8:45                           ` Takashi Yano
2020-07-22 11:49                             ` Corinna Vinschen
2020-07-22 12:13                               ` Ken Brown
2020-07-23  0:33                             ` Takashi Yano
2020-07-24  5:38                               ` Takashi Yano
2020-07-24 11:22                                 ` Takashi Yano
2020-08-02 12:01                                   ` Corinna Vinschen
2020-08-03  2:05                                     ` Takashi Yano
2020-08-03 10:50                                       ` Corinna Vinschen
2020-08-03  2:11                                   ` Takashi Yano
2020-08-03 12:23                                     ` Takashi Yano
2020-08-11 11:12                                       ` Takashi Yano
2020-08-13  9:58                                         ` Takashi Yano
2020-08-17 11:57                                           ` Takashi Yano
2020-08-19 11:39                                             ` Takashi Yano
2020-08-19 13:41                                               ` Corinna Vinschen
2020-08-19 15:43                                                 ` Thomas Wolff
2020-08-19 20:47                                                 ` Mark Geisert
2020-08-20  8:02                                                 ` Takashi Yano
2020-08-31 12:49                                                   ` Johannes Schindelin
2020-08-31 14:14                                                     ` Takashi Yano
     [not found]                                                     ` <20200831231253.332c66fdddb33ceed5f61db6@nifty.ne.jp>
2020-08-31 14:22                                                       ` Johannes Schindelin
2020-08-31 14:53                                                         ` Takashi Yano
2020-08-31 15:56                                                           ` Johannes Schindelin
2020-08-31 16:12                                                             ` Thomas Wolff
2020-08-31 17:39                                                               ` Thomas Wolff
2020-08-31 19:17                                                                 ` Johannes Schindelin
2020-08-31 19:37                                                                   ` Corinna Vinschen
2020-09-01  4:46                                                                     ` Johannes Schindelin
2020-09-01  9:23                                                                       ` Takashi Yano
2020-09-01  6:32                                                                         ` Johannes Schindelin
2020-09-01 22:33                                                                           ` Takashi Yano
2020-09-02  6:13                                                                             ` Johannes Schindelin
2020-09-01  9:42                                                                         ` Takashi Yano
2020-08-31 21:07                                                                   ` Thomas Wolff
2020-08-31 23:23                                                                     ` Takashi Yano
2020-09-01  5:00                                                                     ` Johannes Schindelin
2020-09-01  8:56                                                                       ` Thomas Wolff

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200529004024.0c2ac3c68b588bda987e0837@nifty.ne.jp \
    --to=takashi.yano@nifty.ne.jp \
    --cc=cygwin-developers@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).