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;