Index: sync.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/sync.cc,v
retrieving revision 1.19
diff -u -p -r1.19 sync.cc
--- sync.cc	2001/09/13 01:07:25	1.19
+++ sync.cc	2001/09/17 02:21:57
@@ -28,7 +28,7 @@ muto NO_COPY muto_start;
 #undef WaitForSingleObject
 
 /* Constructor */
-muto::muto (int inh, const char *s) : sync (0), visits(0), waiters(-1), tid (0), next (NULL)
+muto::muto (int inh, const char *s) : sync (0), visits(0), waiters(-1), recover (0), tid (0), thandle (NULL), next (NULL)
 {
   /* Create event which is used in the fallback case when blocking is necessary */
   if (!(bruteforce = CreateEvent (inh ? &sec_all_nih : &sec_none_nih, FALSE, FALSE, name)))
@@ -47,7 +47,7 @@ muto::~muto ()
     release ();
 
   HANDLE h = bruteforce;
-  h = NULL;
+  bruteforce = NULL;
   /* Just need to close the event handle */
   if (h)
     CloseHandle (h);
@@ -64,6 +64,7 @@ int
 muto::acquire (DWORD ms)
 {
   DWORD this_tid = GetCurrentThreadId ();
+  bool recovered = false;
 
   if (tid != this_tid)
     {
@@ -90,6 +91,20 @@ muto::acquire (DWORD ms)
 		goto gotit;
 		break;
 	      default:
+		/* Timed out. The other thread could have died ... */
+		/* only one thread is allowed to 'recover' the muto */
+		if (InterlockedIncrement (&recover) == 1)
+		  {
+		    DWORD status;
+		    GetExitCodeThread (thandle, &status);
+		    if (status != STILL_ACTIVE)
+		      {
+			recovered = true;
+			visits = 0;
+		        goto gotit;
+		      }
+		  }
+		InterlockedDecrement (&recover);
 		InterlockedDecrement (&waiters);
 		return 0;	/* failed. */
 	      }
@@ -97,7 +112,21 @@ muto::acquire (DWORD ms)
     }
 
 gotit:
-  tid = this_tid;	/* register this thread. */
+  if (tid != this_tid)
+    {
+      tid = this_tid;	/* register this thread. */
+      if (thandle)
+	CloseHandle (thandle);
+      DuplicateHandle (GetCurrentProcess (),
+			GetCurrentThread (),
+			GetCurrentProcess (),
+			&thandle,
+			THREAD_QUERY_INFORMATION,
+			FALSE, 0);
+      if (recovered)
+	InterlockedDecrement (&recover);
+    }
+
   return ++visits;	/* Increment visit count. */
 }
 
@@ -117,6 +146,10 @@ muto::release ()
   if (!--visits)
     {
       tid = 0;		/* We were the last unlocker. */
+      if (thandle)
+	CloseHandle (thandle);
+      thandle = NULL;
+      recover = 0;
       (void) InterlockedExchange (&sync, 0); /* Reset trigger. */
       /* This thread had incremented waiters but had never decremented it.
 	 Decrement it now.  If it is >= 0 then there are possibly other
@@ -133,6 +166,9 @@ void
 muto::reset ()
 {
   visits = sync = tid = 0;
+  if (thandle)
+    CloseHandle (thandle);
+  thandle = NULL;
   InterlockedExchange (&waiters, -1);
   if (bruteforce)
     {
Index: sync.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/sync.h,v
retrieving revision 1.13
diff -u -p -r1.13 sync.h
--- sync.h	2001/09/11 20:01:01	1.13
+++ sync.h	2001/09/17 02:21:57
@@ -17,8 +17,10 @@ class muto
   LONG sync;	/* Used to serialize access to this class. */
   LONG visits;	/* Count of number of times a thread has called acquire. */
   LONG waiters;	/* Number of threads waiting for lock. */
+  LONG recover; /* Protection for recovering from a dead thread situation */
   HANDLE bruteforce; /* event handle used to control waiting for lock. */
   DWORD tid;	/* Thread Id of lock owner. */
+  HANDLE thandle; /* slightly more expensive than tid, used to detect thread exits */
 public:
   class muto *next;
   const char *name;
