From 6b2a9a2fdf2a62475c7bb7ff3ef49eee5b82fa6e Mon Sep 17 00:00:00 2001
From: Christopher Faylor <me@cgf.cx>
Date: Fri, 2 Aug 2002 02:10:24 +0000
Subject: [PATCH] * cygthread.cc (cygthread::exit_thread): Define new method. *
 cygthread.h (cygthread::exit_thread): Declare new method. * fhandler.h
 (fhandler_tty_master::hThread): Delete. (fhandler_tty_master::output_thread):
 Define. * fhandler_tty.cc (fhandler_tty_master::fhandler_tty_master): Adjust
 constructor. (fhandler_tty_master::init): Use cygthread rather than handle.
 (process_output): Use cygthread method to exit.
 (fhandler_tty_master::fixup_after_fork): Set output_thread to NULL after
 fork. (fhandler_tty_master::fixup_after_exec): Set output_thread to NULL
 after spawn/exec. * tty.cc (tty_list::terminate): Detach from output_thread
 using cygthread method.

---
 winsup/cygwin/ChangeLog       | 17 +++++++++++++++++
 winsup/cygwin/cygthread.cc    |  7 +++++++
 winsup/cygwin/cygthread.h     |  1 +
 winsup/cygwin/fhandler.h      |  3 ++-
 winsup/cygwin/fhandler_tty.cc | 24 +++++++++++-------------
 winsup/cygwin/syscalls.cc     |  9 +++++----
 winsup/cygwin/tty.cc          |  5 +++--
 7 files changed, 46 insertions(+), 20 deletions(-)

diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index a9daddbce..53ecc8cec 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,20 @@
+2002-08-01  Christopher Faylor  <cgf@redhat.com>
+
+	* cygthread.cc (cygthread::exit_thread): Define new method.
+	* cygthread.h (cygthread::exit_thread): Declare new method.
+	* fhandler.h (fhandler_tty_master::hThread): Delete.
+	(fhandler_tty_master::output_thread): Define.
+	* fhandler_tty.cc (fhandler_tty_master::fhandler_tty_master): Adjust
+	constructor.
+	(fhandler_tty_master::init): Use cygthread rather than handle.
+	(process_output): Use cygthread method to exit.
+	(fhandler_tty_master::fixup_after_fork): Set output_thread to NULL
+	after fork.
+	(fhandler_tty_master::fixup_after_exec): Set output_thread to NULL
+	after spawn/exec.
+	* tty.cc (tty_list::terminate): Detach from output_thread using
+	cygthread method.
+
 2002-08-01  Christopher Faylor  <cgf@redhat.com>
 
 	* syscalls.cc (_link): Revert previous change and just always
diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc
index 66abb7408..a4f32472d 100644
--- a/winsup/cygwin/cygthread.cc
+++ b/winsup/cygwin/cygthread.cc
@@ -147,6 +147,13 @@ HANDLE ()
   return ev;
 }
 
+void
+cygthread::exit_thread ()
+{
+  SetEvent (ev);
+  ExitThread (0);
+}
+
 void
 cygthread::detach ()
 {
diff --git a/winsup/cygwin/cygthread.h b/winsup/cygwin/cygthread.h
index 67e9d591e..b4f6cbe2f 100644
--- a/winsup/cygwin/cygthread.h
+++ b/winsup/cygwin/cygthread.h
@@ -27,4 +27,5 @@ class cygthread
   operator HANDLE ();
   static bool is ();
   void * operator new (size_t);
+  void exit_thread ();
 };
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 17390bdc3..a338987d4 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -921,12 +921,13 @@ class fhandler_pty_master: public fhandler_tty_common
   bool hit_eof ();
 };
 
+class cygthread;
 class fhandler_tty_master: public fhandler_pty_master
 {
  public:
   /* Constructor */
   fhandler_console *console;	// device handler to perform real i/o.
-  HANDLE hThread;		// process_output thread handle.
+  cygthread *output_thread;		// process_output thread
 
   fhandler_tty_master (int unit);
   int init (int);
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 2ead75122..a7b7d814d 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -37,7 +37,7 @@ static DWORD WINAPI process_output (void *);		// Output queue thread
 static DWORD WINAPI process_ioctl (void *);		// Ioctl requests thread
 
 fhandler_tty_master::fhandler_tty_master (int unit)
-  : fhandler_pty_master (FH_TTYM, unit), console (NULL), hThread (NULL)
+  : fhandler_pty_master (FH_TTYM, unit), console (NULL), output_thread (NULL)
 {
 }
 
@@ -69,9 +69,8 @@ fhandler_tty_master::init (int ntty)
   h = new cygthread (process_ioctl, NULL, "ttyioctl");
   SetThreadPriority (*h, THREAD_PRIORITY_HIGHEST);
 
-  h = new cygthread (process_output, NULL, "ttyout");
-  hThread = *h;
-  SetThreadPriority (h, THREAD_PRIORITY_HIGHEST);
+  output_thread = new cygthread (process_output, NULL, "ttyout");
+  SetThreadPriority (*output_thread, THREAD_PRIORITY_HIGHEST);
 
   return 0;
 }
@@ -377,15 +376,13 @@ process_output (void *)
   for (;;)
     {
       int n = tty_master->process_slave_output (buf, OUT_BUFFER_SIZE, 0);
-      if (n < 0)
+      if (n <= 0)
 	{
-	  termios_printf ("ReadFile %E");
-	  ExitThread (0);
-	}
-      if (n == 0)
-	{
-	  /* End of file.  */
-	  ExitThread (0);
+	  if (n < 0)
+	    termios_printf ("ReadFile %E");
+	  cygthread *t = tty_master->output_thread;
+	  tty_master->output_thread = NULL;
+	  t->exit_thread ();
 	}
       n = tty_master->console->write ((void *) buf, (size_t) n);
       tty_master->get_ttyp ()->write_error = n == -1 ? get_errno () : 0;
@@ -1186,6 +1183,7 @@ fhandler_tty_master::fixup_after_fork (HANDLE child)
 {
   this->fhandler_pty_master::fixup_after_fork (child);
   console->fixup_after_fork (child);
+  output_thread = NULL;		// It's unreachable now
 }
 
 void
@@ -1193,7 +1191,7 @@ fhandler_tty_master::fixup_after_exec (HANDLE)
 {
   console->close ();
   init_console ();
-  return;
+  output_thread = NULL;		// It's unreachable now
 }
 
 int
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index a9c9d53c5..4792744e0 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -305,10 +305,11 @@ _read (int fd, void *ptr, size_t len)
       DWORD wait = cfd->is_nonblocking () ? 0 : INFINITE;
 
       /* Could block, so let user know we at least got here.  */
-      syscall_printf ("read (%d, %p, %d) %sblocking, sigcatchers %d", fd, ptr, len, wait ? "" : "non", sigcatchers);
+      syscall_printf ("read (%d, %p, %d) %sblocking, sigcatchers %d",
+		      fd, ptr, len, wait ? "" : "non", sigcatchers);
 
       if (wait && (!cfd->is_slow () || cfd->get_r_no_interrupt ()))
-	debug_printf ("non-interruptible read\n");
+	debug_printf ("no need to call ready_for_read\n");
       else if (!cfd->ready_for_read (fd, wait))
 	{
 	  res = -1;
@@ -318,7 +319,7 @@ _read (int fd, void *ptr, size_t len)
       /* FIXME: This is not thread safe.  We need some method to
 	 ensure that an fd, closed in another thread, aborts I/O
 	 operations. */
-      if (!cfd.isopen())
+      if (!cfd.isopen ())
 	return -1;
 
       /* Check to see if this is a background read from a "tty",
@@ -331,7 +332,7 @@ _read (int fd, void *ptr, size_t len)
       if (res > bg_eof)
 	{
 	  myself->process_state |= PID_TTYIN;
-	  if (!cfd.isopen())
+	  if (!cfd.isopen ())
 	    return -1;
 	  res = cfd->read (ptr, len);
 	  myself->process_state &= ~PID_TTYIN;
diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
index 11c25b161..bb9f8409f 100644
--- a/winsup/cygwin/tty.cc
+++ b/winsup/cygwin/tty.cc
@@ -25,6 +25,7 @@ details. */
 #include "cygwin/cygserver_transport.h"
 #include "cygwin/cygserver.h"
 #include "shared_info.h"
+#include "cygthread.h"
 
 extern fhandler_tty_master *tty_master;
 
@@ -144,8 +145,8 @@ tty_list::terminate (void)
       ForceCloseHandle1 (t->to_slave, to_pty);
       ForceCloseHandle1 (t->from_slave, from_pty);
       CloseHandle (tty_master->inuse);
-      // FIXME This should be using a cygthread object
-      WaitForSingleObject (tty_master->hThread, INFINITE);
+      if (tty_master->output_thread)
+	tty_master->output_thread->detach ();
       t->init ();
 
       char buf[20];