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: Wed, 1 Jul 2020 20:47:51 +0900	[thread overview]
Message-ID: <20200701204751.27609a8f5701010468521a87@nifty.ne.jp> (raw)
In-Reply-To: <20200529004024.0c2ac3c68b588bda987e0837@nifty.ne.jp>

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

On Fri, 29 May 2020 00:40:24 +0900
Takashi Yano via Cygwin-developers <cygwin-developers@cygwin.com> wrote:
> 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.

Revise the patch to fit the current git head.

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

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

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index c6ce6d8e1..10ef2ae4a 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -2265,6 +2265,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,8 @@ class fhandler_pty_slave: public fhandler_pty_common
   void trigger_redraw_screen (void);
   void pull_pcon_input (void);
   void update_pcon_input_state (bool need_lock);
+  bool setup_pseudoconsole2 (STARTUPINFOEXW *si);
+  void close_pseudoconsole2 (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 a61167116..adaf2352c 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);
 }
 
@@ -535,7 +567,7 @@ fhandler_pty_master::doecho (const void *str, DWORD len)
 int
 fhandler_pty_master::put_readahead (char value)
 {
-  if (to_be_read_from_pcon ())
+  if (to_be_read_from_pcon () && !USE_PCON_MODE2)
     return 1;
   return fhandler_base::put_readahead (value);
 }
@@ -551,7 +583,11 @@ fhandler_pty_master::accept_input ()
   char *p = rabuf () + raixget ();
   bytes_left = eat_readahead (-1);
 
-  if (to_be_read_from_pcon ())
+  HANDLE write_to = get_output_handle ();
+  if (to_be_read_from_pcon () && USE_PCON_MODE2)
+    write_to = to_slave;
+
+  if (to_be_read_from_pcon () && !USE_PCON_MODE2)
     ; /* Do nothing */
   else if (!bytes_left)
     {
@@ -564,10 +600,10 @@ fhandler_pty_master::accept_input ()
       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;
 	}
@@ -1278,6 +1314,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;
+    }
   acquire_output_mutex (INFINITE);
   if (fd == 0 && !get_ttyp ()->switch_to_pcon_in)
     {
@@ -1326,6 +1374,7 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
   get_ttyp ()->switch_to_pcon_out = false;
   release_output_mutex ();
   init_console_handler (true);
+  get_ttyp ()->h_pseudo_console2 = NULL;
 }
 
 void
@@ -1589,8 +1638,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
@@ -2098,6 +2148,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);
@@ -2383,6 +2435,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 ()
 {
@@ -2518,7 +2591,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
@@ -2530,11 +2604,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)
@@ -2560,6 +2675,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;
@@ -2644,6 +2760,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);
 	}
@@ -3062,6 +3180,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
@@ -3262,6 +3386,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");
@@ -3269,8 +3395,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)
@@ -3314,6 +3441,10 @@ fhandler_pty_master::pty_master_fwd_thread ()
 	  /* Remove CSI > Pm m */
 	  state = 0;
 	  start_at = 0;
+#else /* USE_PCON_MODE2 */
+	  int state = 0;
+	  int start_at = 0;
+#endif /* USE_PCON_MODE2 */
 	  for (DWORD i=0; i<rlen; i++)
 	    if (outbuf[i] == '\033')
 	      {
@@ -3704,7 +3835,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);
@@ -3722,6 +3865,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);
@@ -3866,3 +4010,124 @@ 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)
+    return false;
+  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 (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)
+    {
+      get_ttyp ()->wait_pcon_fwd ();
+      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..9c4068106 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,11 @@ 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->close_pseudoconsole2 ();
+	    }
 	  myself.exit (EXITCODE_NOSET);
 	  break;
 	case _P_WAIT:
diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
index 4cb68f776..1d296f36e 100644
--- a/winsup/cygwin/tty.cc
+++ b/winsup/cygwin/tty.cc
@@ -248,6 +248,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 920e32b16..9372f73b2 100644
--- a/winsup/cygwin/tty.h
+++ b/winsup/cygwin/tty.h
@@ -109,6 +109,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; }

  parent reply	other threads:[~2020-07-01 11:48 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
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 [this message]
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=20200701204751.27609a8f5701010468521a87@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).