Fix race condition in thread pool shutdown
We were not holding the task queue lock when we did broadcast, causing
a race where a thread waits on the CV after the broadcast.
Fixes dex2oat deadlocking.
Change-Id: I84f30020511c2bd43f71d9b7b392720bd8d03eab
diff --git a/src/mutex.cc b/src/mutex.cc
index a4347ba..0e33f3c 100644
--- a/src/mutex.cc
+++ b/src/mutex.cc
@@ -749,6 +749,7 @@
DCHECK(self == NULL || self == Thread::Current());
// TODO: enable below, there's a race in thread creation that causes false failures currently.
// guard_.AssertExclusiveHeld(self);
+ DCHECK_EQ(guard_.GetExclusiveOwnerTid(), SafeGetTid(self));
#if ART_USE_FUTEXES
if (num_waiters_ > 0) {
android_atomic_inc(&state_); // Indicate a wake has occurred to waiters coming in.
diff --git a/src/thread_pool.cc b/src/thread_pool.cc
index fa0cf79..f3319e2 100644
--- a/src/thread_pool.cc
+++ b/src/thread_pool.cc
@@ -69,11 +69,15 @@
}
ThreadPool::~ThreadPool() {
- // Tell any remaining workers to shut down.
- shutting_down_ = true;
- android_memory_barrier();
- // Broadcast to everyone waiting.
- task_queue_condition_.Broadcast(Thread::Current());
+ {
+ Thread* self = Thread::Current();
+ MutexLock mu(self, task_queue_lock_);
+ // Tell any remaining workers to shut down.
+ shutting_down_ = true;
+ android_memory_barrier();
+ // Broadcast to everyone waiting.
+ task_queue_condition_.Broadcast(self);
+ }
// Wait for the threads to finish.
STLDeleteElements(&threads_);
}