OSDN Git Service

Bug 5044578 Fix race in engine destroy on uni
authorGlenn Kasten <gkasten@google.com>
Tue, 19 Jul 2011 00:37:40 +0000 (17:37 -0700)
committerGlenn Kasten <gkasten@google.com>
Tue, 19 Jul 2011 17:28:00 +0000 (10:28 -0700)
On uniprocessor, the main thread reached Engine::Destroy before the
worker threads had even started, so they did not see the shutdown.

On SMP, the worker threads were started (and blocked), so it was OK.

This new code also has the advantage of shutting down quicker
if there are pending callback requests in the queue.

Change-Id: Iff8cca042ebffe48ce7cc5d798e7b3b9911fb64b

wilhelm/src/ThreadPool.c

index 6cfb072..a910018 100644 (file)
@@ -332,26 +332,25 @@ Closure *ThreadPool_remove(ThreadPool *tp)
     ok = pthread_mutex_lock(&tp->mMutex);
     assert(0 == ok);
     for (;;) {
+        // fail if thread pool is shutting down
+        if (tp->mShutdown) {
+            pClosure = NULL;
+            break;
+        }
         Closure **oldFront = tp->mClosureFront;
         // if closure circular buffer is empty, then wait for it to become non-empty
         if (oldFront == tp->mClosureRear) {
             ++tp->mWaitingNotEmpty;
             ok = pthread_cond_wait(&tp->mCondNotEmpty, &tp->mMutex);
             assert(0 == ok);
-            // fail if thread pool is shutting down
-            if (tp->mShutdown) {
-                assert(0 < tp->mWaitingNotEmpty);
-                --tp->mWaitingNotEmpty;
-                pClosure = NULL;
-                break;
-            }
             // try again
             continue;
         }
         // dequeue the closure at front of circular buffer
         Closure **newFront = oldFront;
-        if (++newFront == &tp->mClosureArray[tp->mMaxClosures + 1])
+        if (++newFront == &tp->mClosureArray[tp->mMaxClosures + 1]) {
             newFront = tp->mClosureArray;
+        }
         pClosure = *oldFront;
         assert(NULL != pClosure);
         *oldFront = NULL;