Merge "Avoid using ThreadList::Dump() in empty checkpoint timeout."
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index b889913..dccec9f 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -843,8 +843,26 @@
ss << "\n";
Locks::mutator_lock_->Dump(ss);
ss << "\n";
- runtime->GetThreadList()->Dump(ss);
- LOG(FATAL) << ss.str();
+ LOG(FATAL_WITHOUT_ABORT) << ss.str();
+ // Some threads in 'runnable_thread_ids' are probably stuck. Try to dump their stacks.
+ // Avoid using ThreadList::Dump() because it is likely to get stuck as well.
+ {
+ ReaderMutexLock mu0(self, *Locks::mutator_lock_);
+ MutexLock mu1(self, *Locks::thread_list_lock_);
+ for (Thread* thread : runtime->GetThreadList()->GetList()) {
+ uint32_t tid = thread->GetThreadId();
+ bool is_in_runnable_thread_ids =
+ std::find(runnable_thread_ids.begin(), runnable_thread_ids.end(), tid) !=
+ runnable_thread_ids.end();
+ if (is_in_runnable_thread_ids &&
+ thread->ReadFlag(kEmptyCheckpointRequest)) {
+ // Found a runnable thread that hasn't responded to the empty checkpoint request.
+ // Assume it's stuck and safe to dump its stack.
+ thread->Dump(LOG_STREAM(FATAL_WITHOUT_ABORT));
+ }
+ }
+ }
+ LOG(FATAL) << "Dumped runnable threads that haven't responded to empty checkpoint.";
}
} else {
barrier->Increment(self, barrier_count);