From dc000a838679572cba87587a7548d8fce4c44aa9 Mon Sep 17 00:00:00 2001
From: Christopher Faylor <me@cgf.cx>
Date: Mon, 28 Mar 2005 19:31:23 +0000
Subject: [PATCH] * cygthread.cc (cygthread::detach): Revert to just waiting
 for thred event since waiting for anything else is racy. * timer.cc
 (timer_tracker::hcancel): Rename from cancel. (timer_tracker::cancel): New
 method. (timer_tracker::th): Remove. (timer_tracker::~timer_tracker): Call
 cancel method. (timer_tracker::timer_tracker): Ditto.
 (timer_tracker::timer_tracker): Always, clear cancel, even though it is
 probably not strictly necessary for ttstart. (timer_thread): Accommodate
 cancel -> hcancel rename. (timer_tracker::settime): Ditto.
 (timer_tracker::gettime): Ditto. (timer_delete): Ditto. * cygwin.din: Export
 _ctype_. * include/ctype.h: Mark that _ctype_ is imported.

---
 winsup/cygwin/ChangeLog       | 19 ++++++++++++++
 winsup/cygwin/cygthread.cc    |  2 +-
 winsup/cygwin/cygwin.din      |  1 +
 winsup/cygwin/include/ctype.h |  4 +++
 winsup/cygwin/timer.cc        | 49 +++++++++++++++++++----------------
 5 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ad2c2267f..a868a00a5 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,22 @@
+2005-03-28  Christopher Faylor  <cgf@timesys.com>
+
+	* cygthread.cc (cygthread::detach): Revert to just waiting for thred
+	event since waiting for anything else is racy.
+	* timer.cc (timer_tracker::hcancel): Rename from cancel.
+	(timer_tracker::cancel): New method.
+	(timer_tracker::th): Remove.
+	(timer_tracker::~timer_tracker): Call cancel method.
+	(timer_tracker::timer_tracker): Ditto.
+	(timer_tracker::timer_tracker): Always, clear cancel, even though it is
+	probably not strictly necessary for ttstart.
+	(timer_thread): Accommodate cancel -> hcancel rename.
+	(timer_tracker::settime): Ditto.
+	(timer_tracker::gettime): Ditto.
+	(timer_delete): Ditto.
+
+	* cygwin.din: Export _ctype_.
+	* include/ctype.h: Mark that _ctype_ is imported.
+
 2005-03-28  Christopher Faylor  <cgf@timesys.com>
 
 	* timer.cc (timer_tracker::timer_tracker): Eliminate simple
diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc
index 11fb047dd..59b13be4f 100644
--- a/winsup/cygwin/cygthread.cc
+++ b/winsup/cygwin/cygthread.cc
@@ -315,7 +315,7 @@ cygthread::detach (HANDLE sigwait)
       if (!sigwait)
 	/* If the caller specified a special handle for notification, wait for that.
 	   This assumes that the thread in question is auto releasing. */
-	res = WaitForSingleObject (notify_detached ?: *this, INFINITE);
+	res = WaitForSingleObject (*this, INFINITE);
       else
 	{
 	  /* Lower our priority and give priority to the read thread */
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 5d593270e..9a09c7a89 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -4,6 +4,7 @@ EXPORTS
 __argc DATA
 __argv DATA
 __check_rhosts_file DATA
+_ctype_ DATA
 __cygwin_environ DATA
 __cygwin_user_data DATA
 __mb_cur_max DATA
diff --git a/winsup/cygwin/include/ctype.h b/winsup/cygwin/include/ctype.h
index c317a30cd..8b0ca03ca 100644
--- a/winsup/cygwin/include/ctype.h
+++ b/winsup/cygwin/include/ctype.h
@@ -38,7 +38,11 @@ int __cdecl _toupper(int);
 #define _X	0100
 #define	_B	0200
 
+#ifdef __INSIDE_CYGWIN__
 extern const char _ctype_[];
+#else
+extern const __declspec(dllimport) char _ctype_[];
+#endif
 
 #if !defined(__cplusplus) || defined(__INSIDE_CYGWIN__)
 #define	isalpha(c)	((_ctype_+1)[(unsigned)(c)]&(_U|_L))
diff --git a/winsup/cygwin/timer.cc b/winsup/cygwin/timer.cc
index fccc4656f..60149bad4 100644
--- a/winsup/cygwin/timer.cc
+++ b/winsup/cygwin/timer.cc
@@ -26,11 +26,11 @@ struct timer_tracker
   clockid_t clock_id;
   sigevent evp;
   timespec it_interval;
-  HANDLE cancel;
+  HANDLE hcancel;
   HANDLE syncthread;
   long long interval_us;
   long long sleepto_us;
-  cygthread *th;
+  bool cancel ();
   struct timer_tracker *next;
   int settime (int, const itimerspec *, itimerspec *);
   void gettime (itimerspec *);
@@ -61,16 +61,25 @@ lock_timer_tracker::~lock_timer_tracker ()
   protect->release ();
 }
 
+bool
+timer_tracker::cancel ()
+{
+  if (!hcancel)
+    return false;
+    
+  SetEvent (hcancel);
+  if (WaitForSingleObject (syncthread, INFINITE) != WAIT_OBJECT_0)
+    api_fatal ("WFSO failed waiting for timer thread, %E");
+  return true;
+}
+
 timer_tracker::~timer_tracker ()
 {
-  if (cancel)
+  if (cancel ())
     {
-      SetEvent (cancel);
-      th->detach ();
-      CloseHandle (cancel);
+      CloseHandle (hcancel);
 #ifdef DEBUGGING
-      th = NULL;
-      cancel = NULL;
+      hcancel = NULL;
 #endif
     }
   if (syncthread)
@@ -90,9 +99,9 @@ timer_tracker::timer_tracker (clockid_t c, const sigevent *e)
     }
   clock_id = c;
   magic = TT_MAGIC;
+  hcancel = NULL;
   if (this != &ttstart)
     {
-      cancel = NULL;
       lock_timer_tracker here;
       next = ttstart.next;
       ttstart.next = this;
@@ -134,7 +143,7 @@ timer_thread (VOID *x)
 	}
 
       debug_printf ("%p waiting for %u ms", x, sleep_ms);
-      switch (WaitForSingleObject (tt->cancel, sleep_ms))
+      switch (WaitForSingleObject (tt->hcancel, sleep_ms))
 	{
 	case WAIT_TIMEOUT:
 	  debug_printf ("timed out");
@@ -216,11 +225,7 @@ timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalu
   long long now = in_flags & TIMER_ABSTIME ? 0 : gtod.usecs (false);
 
   lock_timer_tracker here;
-  if (cancel)
-    {
-      SetEvent (cancel);	// should be closed when the thread exits
-      th->detach ();
-    }
+  cancel ();
 
   if (ovalue)
     gettime (ovalue);
@@ -230,15 +235,15 @@ timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalu
       sleepto_us = now + to_us (value->it_value);
       interval_us = to_us (value->it_interval);
       it_interval = value->it_interval;
-      if (!cancel)
-	cancel = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
+      if (!hcancel)
+	hcancel = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
       else
-	ResetEvent (cancel);
+	ResetEvent (hcancel);
       if (!syncthread)
 	syncthread = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
       else
 	ResetEvent (syncthread);
-      th = new cygthread (timer_thread, this, "itimer", syncthread);
+      (void) new cygthread (timer_thread, this, "itimer", syncthread);
     }
 
   return 0;
@@ -247,7 +252,7 @@ timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalu
 void
 timer_tracker::gettime (itimerspec *ovalue)
 {
-  if (!cancel)
+  if (!hcancel)
     memset (ovalue, 0, sizeof (*ovalue));
   else
     {
@@ -333,12 +338,12 @@ timer_delete (timer_t timerid)
 void
 fixup_timers_after_fork ()
 {
-  ttstart.cancel = ttstart.syncthread = NULL;
+  ttstart.hcancel = ttstart.syncthread = NULL;
   for (timer_tracker *tt = &ttstart; tt->next != NULL; /* nothing */)
     {
       timer_tracker *deleteme = tt->next;
       tt->next = deleteme->next;
-      deleteme->cancel = deleteme->syncthread = NULL;
+      deleteme->hcancel = deleteme->syncthread = NULL;
       delete deleteme;
     }
 }