Fixes for ThreadStress test
- Fix deadlock when ThreadGroup.remove(Thread) was run with
thread_list_lock_ but needed to GC to allocate an iterator
- Fix ~MonitorList to clean ownership of any locks that might be held
by JNI or daemon threads on shutdown.
Change-Id: I95e23c3b7c745f6a8387789949f3ec849458a27d
diff --git a/src/thread_list.cc b/src/thread_list.cc
index 8969868..dfce2a2 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -29,8 +29,13 @@
// simultaneously by going to kVmWait if the lock cannot be
// immediately acquired.
if (!thread_list_->thread_list_lock_.TryLock()) {
- ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
- thread_list_->thread_list_lock_.Lock();
+ Thread* self = Thread::Current();
+ if (self == NULL) {
+ thread_list_->thread_list_lock_.Lock();
+ } else {
+ ScopedThreadStateChange tsc(self, Thread::kVmWait);
+ thread_list_->thread_list_lock_.Lock();
+ }
}
}
@@ -294,9 +299,18 @@
LOG(INFO) << "ThreadList::Unregister() " << *self;
}
- // This may need to call user-supplied managed code. Make sure we do this before we start tearing
- // down the Thread* and removing it from the thread list (or start taking any locks).
- self->HandleUncaughtExceptions();
+ if (self->GetPeer() != NULL) {
+ self->SetState(Thread::kRunnable);
+
+ // This may need to call user-supplied managed code. Make sure we do this before we start tearing
+ // down the Thread* and removing it from the thread list (or start taking any locks).
+ self->HandleUncaughtExceptions();
+
+ // Make sure we remove from ThreadGroup before taking the
+ // thread_list_lock_ since it allocates an Iterator which can cause
+ // a GC which will want to suspend.
+ self->RemoveFromThreadGroup();
+ }
ThreadListLocker locker(this);