diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 694c23b..6911277 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -412,6 +412,7 @@ public:
      that some fd's have two handles. */
   virtual HANDLE& get_handle () { return io_handle; }
   virtual HANDLE& get_io_handle () { return io_handle; }
+  virtual HANDLE& get_io_handle2 () { return io_handle; }
   virtual HANDLE& get_output_handle () { return io_handle; }
   virtual HANDLE get_stat_handle () { return pc.handle () ?: io_handle; }
   virtual HANDLE get_echo_handle () const { return NULL; }
@@ -1516,6 +1517,7 @@ class fhandler_pty_common: public fhandler_termios
 class fhandler_pty_slave: public fhandler_pty_common
 {
   HANDLE inuse;			// used to indicate that a tty is in use
+  HANDLE output_handle2;
 
   /* Helper functions for fchmod and fchown. */
   bool fch_open_handles (bool chown);
@@ -1526,6 +1528,9 @@ class fhandler_pty_slave: public fhandler_pty_common
   /* Constructor */
   fhandler_pty_slave (int);
 
+  void set_output_handle2 (HANDLE h) { output_handle2 = h; }
+  HANDLE& get_output_handle2 () { return output_handle2; }
+
   int open (int flags, mode_t mode = 0);
   void open_setup (int flags);
   ssize_t __stdcall write (const void *ptr, size_t len);
@@ -1575,13 +1580,17 @@ class fhandler_pty_master: public fhandler_pty_common
   HANDLE from_master, to_master;
   HANDLE echo_r, echo_w;
   DWORD dwProcessId;		// Owner of master handles
+  HANDLE io_handle2, to_master2;
+  cygthread *master_fwd_thread;	// Master forwarding thread
 
 public:
   HANDLE get_echo_handle () const { return echo_r; }
+  HANDLE& get_io_handle2 () { return io_handle2; }
   /* Constructor */
   fhandler_pty_master (int);
 
   DWORD pty_master_thread ();
+  DWORD pty_master_fwd_thread ();
   int process_slave_output (char *buf, size_t len, int pktmode_on);
   void doecho (const void *str, DWORD len);
   int accept_input ();
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index ccb76d9..f319495 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -42,6 +42,7 @@ struct pipe_request {
 struct pipe_reply {
   HANDLE from_master;
   HANDLE to_master;
+  HANDLE to_master2;
   DWORD error;
 };
 
@@ -236,7 +237,7 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on
 	  /* Check echo pipe first. */
 	  if (::bytes_available (echo_cnt, echo_r) && echo_cnt > 0)
 	    break;
-	  if (!bytes_available (n))
+	  if (!::bytes_available (n, get_io_handle2 ()))
 	    goto err;
 	  if (n)
 	    break;
@@ -297,7 +298,7 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on
 	      goto err;
 	    }
 	}
-      else if (!ReadFile (get_handle (), outbuf, rlen, &n, NULL))
+      else if (!ReadFile (get_io_handle2 (), outbuf, rlen, &n, NULL))
 	{
 	  termios_printf ("ReadFile failed, %E");
 	  goto err;
@@ -332,7 +333,7 @@ out:
 /* pty slave stuff */
 
 fhandler_pty_slave::fhandler_pty_slave (int unit)
-  : fhandler_pty_common (), inuse (NULL)
+  : fhandler_pty_common (), inuse (NULL), output_handle2 (NULL)
 {
   if (unit >= 0)
     dev ().parse (DEV_PTYS_MAJOR, unit);
@@ -341,11 +342,11 @@ fhandler_pty_slave::fhandler_pty_slave (int unit)
 int
 fhandler_pty_slave::open (int flags, mode_t)
 {
-  HANDLE pty_owner, from_master_local, to_master_local;
+  HANDLE pty_owner, from_master_local, to_master_local, to_master2_local;
   HANDLE *handles[] =
   {
     &from_master_local, &input_available_event, &input_mutex, &inuse,
-    &output_mutex, &to_master_local, &pty_owner,
+    &output_mutex, &to_master_local, &pty_owner, &to_master2_local,
     NULL
   };
 
@@ -396,7 +397,8 @@ fhandler_pty_slave::open (int flags, mode_t)
     release_output_mutex ();
   }
 
-  if (!get_ttyp ()->from_master () || !get_ttyp ()->to_master ())
+  if (!get_ttyp ()->from_master () ||
+      !get_ttyp ()->to_master () || !get_ttyp ()->to_master2 ())
     {
       errmsg = "pty handles have been closed";
       set_errno (EACCES);
@@ -447,6 +449,13 @@ fhandler_pty_slave::open (int flags, mode_t)
 	  errmsg = "can't duplicate output, %E";
 	  goto err;
 	}
+      if (!DuplicateHandle (pty_owner, get_ttyp ()->to_master2 (),
+			  GetCurrentProcess (), &to_master2_local, 0, TRUE,
+			  DUPLICATE_SAME_ACCESS))
+	{
+	  errmsg = "can't duplicate output2, %E";
+	  goto err;
+	}
       if (pty_owner != GetCurrentProcess ())
 	CloseHandle (pty_owner);
     }
@@ -467,7 +476,8 @@ fhandler_pty_slave::open (int flags, mode_t)
 	}
       from_master_local = repl.from_master;
       to_master_local = repl.to_master;
-      if (!from_master_local || !to_master_local)
+      to_master2_local = repl.to_master2;
+      if (!from_master_local || !to_master_local || !to_master2_local)
 	{
 	  SetLastError (repl.error);
 	  errmsg = "error duplicating pipes, %E";
@@ -476,14 +486,18 @@ fhandler_pty_slave::open (int flags, mode_t)
     }
   VerifyHandle (from_master_local);
   VerifyHandle (to_master_local);
+  VerifyHandle (to_master2_local);
 
   termios_printf ("duplicated from_master %p->%p from pty_owner",
 		  get_ttyp ()->from_master (), from_master_local);
   termios_printf ("duplicated to_master %p->%p from pty_owner",
 		  get_ttyp ()->to_master (), to_master_local);
+  termios_printf ("duplicated to_master2 %p->%p from pty_owner",
+		  get_ttyp ()->to_master2 (), to_master2_local);
 
   set_io_handle (from_master_local);
   set_output_handle (to_master_local);
+  set_output_handle2 (to_master2_local);
 
   fhandler_console::need_invisible ();
   set_open_status ();
@@ -532,6 +546,9 @@ fhandler_pty_slave::close ()
     termios_printf ("CloseHandle (inuse), %E");
   if (!ForceCloseHandle (input_available_event))
     termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
+  if (!ForceCloseHandle (get_output_handle2 ()))
+    termios_printf ("CloseHandle (get_output_handle ()<%p>), %E",
+	get_output_handle2 ());
   if ((unsigned) myself->ctty == FHDEV (DEV_PTYS_MAJOR, get_minor ()))
     fhandler_console::free_console ();	/* assumes that we are the last pty closer */
   return fhandler_pty_common::close ();
@@ -590,7 +607,7 @@ fhandler_pty_slave::write (const void *ptr, size_t len)
 
   push_process_state process_state (PID_TTYOU);
 
-  if (!process_opost_output (get_output_handle (), ptr, towrite, false))
+  if (!process_opost_output (get_output_handle2 (), ptr, towrite, false))
     {
       DWORD err = GetLastError ();
       termios_printf ("WriteFile failed, %E");
@@ -1068,6 +1085,7 @@ fhandler_pty_slave::fch_close_handles ()
 {
   close_maybe (get_io_handle ());
   close_maybe (get_output_handle ());
+  close_maybe (get_output_handle2 ());
   close_maybe (input_available_event);
   close_maybe (output_mutex);
   close_maybe (input_mutex);
@@ -1140,7 +1158,8 @@ errout:
 fhandler_pty_master::fhandler_pty_master (int unit)
   : fhandler_pty_common (), pktmode (0), master_ctl (NULL),
     master_thread (NULL), from_master (NULL), to_master (NULL),
-    echo_r (NULL), echo_w (NULL), dwProcessId (0)
+    echo_r (NULL), echo_w (NULL), dwProcessId (0),
+    io_handle2 (NULL), to_master2 (NULL), master_fwd_thread (NULL)
 {
   if (unit >= 0)
     dev ().parse (DEV_PTYM_MAJOR, unit);
@@ -1198,15 +1217,15 @@ fhandler_pty_master::cleanup ()
 {
   report_tty_counts (this, "closing master", "");
   if (archetype)
-    from_master = to_master = NULL;
+    from_master = to_master = to_master2 = NULL;
   fhandler_base::cleanup ();
 }
 
 int
 fhandler_pty_master::close ()
 {
-  termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%u)",
-		  from_master, to_master, dwProcessId);
+  termios_printf ("closing from_master(%p)/to_master(%p)/to_master2(%p) since we own them(%u)",
+		  from_master, to_master, to_master2, dwProcessId);
   if (cygwin_finished_initializing)
     {
       if (master_ctl && get_ttyp ()->master_pid == myself->pid)
@@ -1229,6 +1248,7 @@ fhandler_pty_master::close ()
 	      master_ctl = NULL;
 	    }
 	  release_output_mutex ();
+	  master_fwd_thread->terminate_thread ();
 	}
     }
 
@@ -1245,6 +1265,11 @@ fhandler_pty_master::close ()
   if (!ForceCloseHandle (to_master))
     termios_printf ("error closing to_master %p, %E", to_master);
   from_master = to_master = NULL;
+  if (!ForceCloseHandle (get_io_handle2 ()))
+    termios_printf ("error closing io_handle2 %p, %E", get_io_handle2 ());
+  if (!ForceCloseHandle (to_master2))
+    termios_printf ("error closing to_master2 %p, %E", to_master2);
+  get_io_handle2 () = to_master2 = NULL;
   ForceCloseHandle (echo_r);
   ForceCloseHandle (echo_w);
   echo_r = echo_w = NULL;
@@ -1351,7 +1376,7 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
     case FIONREAD:
       {
 	DWORD n;
-	if (!::bytes_available (n, to_master))
+	if (!::bytes_available (n, get_io_handle2 ()))
 	  {
 	    set_errno (EINVAL);
 	    return -1;
@@ -1521,6 +1546,13 @@ fhandler_pty_master::pty_master_thread ()
 	      termios_printf ("DuplicateHandle (to_master), %E");
 	      goto reply;
 	    }
+	  if (!DuplicateHandle (GetCurrentProcess (), to_master2,
+				client, &repl.to_master2,
+				0, TRUE, DUPLICATE_SAME_ACCESS))
+	    {
+	      termios_printf ("DuplicateHandle (to_master2), %E");
+	      goto reply;
+	    }
 	}
 reply:
       repl.error = GetLastError ();
@@ -1546,6 +1578,40 @@ pty_master_thread (VOID *arg)
   return ((fhandler_pty_master *) arg)->pty_master_thread ();
 }
 
+DWORD
+fhandler_pty_master::pty_master_fwd_thread ()
+{
+  DWORD rlen;
+  char outbuf[OUT_BUFFER_SIZE];
+
+  termios_printf("Started.");
+  for (;;)
+    {
+      if (!ReadFile (get_io_handle (), outbuf, sizeof outbuf, &rlen, NULL))
+	{
+	  termios_printf ("ReadFile for forwarding failed, %E");
+	  break;
+	}
+      ssize_t wlen = rlen;
+      while (rlen>0)
+	{
+	  if (!process_opost_output (to_master2, outbuf, wlen, false))
+	    {
+	      termios_printf ("WriteFile for forwarding failed, %E");
+	      break;
+	    }
+	  rlen -= wlen;
+	}
+    }
+  return 0;
+}
+
+static DWORD WINAPI
+pty_master_fwd_thread (VOID *arg)
+{
+  return ((fhandler_pty_master *) arg)->pty_master_fwd_thread ();
+}
+
 bool
 fhandler_pty_master::setup ()
 {
@@ -1582,6 +1648,15 @@ fhandler_pty_master::setup ()
       goto err;
     }
 
+  __small_sprintf (pipename, "pty%d-to-master2", unit);
+  res = fhandler_pipe::create (&sec_none, &get_io_handle2 (), &to_master2,
+			       fhandler_pty_common::pipesize, pipename, 0);
+  if (res)
+    {
+      errstr = "output pipe 2";
+      goto err;
+    }
+
   ProtectHandle1 (get_io_handle (), from_pty);
 
   __small_sprintf (pipename, "pty%d-echoloop", unit);
@@ -1640,28 +1715,37 @@ fhandler_pty_master::setup ()
       errstr = "pty master control thread";
       goto err;
     }
+  master_fwd_thread = new cygthread (::pty_master_fwd_thread, this, "ptym");
+  if (!master_fwd_thread)
+    {
+      errstr = "pty master forwarding thread";
+      goto err;
+    }
 
   t.set_from_master (from_master);
   t.set_to_master (to_master);
+  t.set_to_master2 (to_master2);
   t.winsize.ws_col = 80;
   t.winsize.ws_row = 25;
   t.master_pid = myself->pid;
 
   dev ().parse (DEV_PTYM_MAJOR, unit);
 
-  termios_printf ("this %p, pty%d opened - from_pty %p, to_pty %p", this, unit,
-		  get_io_handle (), get_output_handle ());
+  termios_printf ("this %p, pty%d opened - from_pty <%p,%p>, to_pty %p",
+	this, unit, get_io_handle (), get_io_handle2 (), get_output_handle ());
   return true;
 
 err:
   __seterrno ();
   close_maybe (get_io_handle ());
+  close_maybe (get_io_handle2 ());
   close_maybe (get_output_handle ());
   close_maybe (input_available_event);
   close_maybe (output_mutex);
   close_maybe (input_mutex);
   close_maybe (from_master);
   close_maybe (to_master);
+  close_maybe (to_master2);
   close_maybe (echo_r);
   close_maybe (echo_w);
   close_maybe (master_ctl);
@@ -1681,11 +1765,13 @@ fhandler_pty_master::fixup_after_fork (HANDLE parent)
 	{
 	  t.set_from_master (arch->from_master);
 	  t.set_to_master (arch->to_master);
+	  t.set_to_master2 (arch->to_master2);
 	}
       arch->dwProcessId = wpid;
     }
   from_master = arch->from_master;
   to_master = arch->to_master;
+  to_master2 = arch->to_master2;
   report_tty_counts (this, "inherited master", "");
 }
 
@@ -1695,7 +1781,7 @@ fhandler_pty_master::fixup_after_exec ()
   if (!close_on_exec ())
     fixup_after_fork (spawn_info->parent);
   else
-    from_master = to_master = NULL;
+    from_master = to_master = to_master2 = NULL;
 }
 
 BOOL
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 1706c87..1b65280 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -80,7 +80,7 @@ details. */
 #define copyfd_set(to, from, n) memcpy (to, from, sizeof_fd_set (n));
 
 #define set_handle_or_return_if_not_open(h, s) \
-  h = (s)->fh->get_handle (); \
+  h = (s)->fh->get_io_handle2 (); \
   if (cygheap->fdtab.not_open ((s)->fd)) \
     { \
       (s)->thread_errno =  EBADF; \
@@ -1264,7 +1264,7 @@ fhandler_base::select_read (select_stuff *ss)
       s->startup = no_startup;
       s->verify = verify_ok;
     }
-  s->h = get_handle ();
+  s->h = get_io_handle2 ();
   s->read_selected = true;
   s->read_ready = true;
   return s;
diff --git a/winsup/cygwin/tty.h b/winsup/cygwin/tty.h
index 27d43f7..cf3508a 100644
--- a/winsup/cygwin/tty.h
+++ b/winsup/cygwin/tty.h
@@ -92,12 +92,15 @@ public:
 private:
   HANDLE _from_master;
   HANDLE _to_master;
+  HANDLE _to_master2;
 
 public:
   HANDLE from_master() const { return _from_master; }
   HANDLE to_master() const { return _to_master; }
+  HANDLE to_master2() const { return _to_master2; }
   void set_from_master (HANDLE h) { _from_master = h; }
   void set_to_master (HANDLE h) { _to_master = h; }
+  void set_to_master2 (HANDLE h) { _to_master2 = h; }
 
   int read_retval;
   bool was_opened;	/* True if opened at least once. */
