summaryrefslogtreecommitdiffstats
path: root/runtime/runtime.cc
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2014-04-10 18:06:32 -0700
committerMathieu Chartier <mathieuc@google.com>2014-04-10 18:07:46 -0700
commitc7a966dbba6902618ff0959d604c05d7570df8c8 (patch)
tree9c29dc008ad24e97ba26d5734fc7db4a41f7ca52 /runtime/runtime.cc
parent22839a631bb3591a1c0037c388d51a4f18b5fb5e (diff)
downloadart-c7a966dbba6902618ff0959d604c05d7570df8c8.zip
art-c7a966dbba6902618ff0959d604c05d7570df8c8.tar.gz
art-c7a966dbba6902618ff0959d604c05d7570df8c8.tar.bz2
Prevent deadlocks in Runtime::Abort.
If we have the threads suspended, attempting to use a ScopedObjectAccess causes a deadlock. We now specifically avoid this to prevent deadlocks. Bug: 13747880 Change-Id: I45fd3fff917da98b22970e5351a9e25b143a4eed
Diffstat (limited to 'runtime/runtime.cc')
-rw-r--r--runtime/runtime.cc33
1 files changed, 20 insertions, 13 deletions
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index a19fa53..5c31d35 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -188,7 +188,7 @@ Runtime::~Runtime() {
}
struct AbortState {
- void Dump(std::ostream& os) {
+ void Dump(std::ostream& os) NO_THREAD_SAFETY_ANALYSIS {
if (gAborting > 1) {
os << "Runtime aborting --- recursively, so no thread-specific detail!\n";
return;
@@ -200,26 +200,33 @@ struct AbortState {
return;
}
Thread* self = Thread::Current();
- if (self == NULL) {
+ if (self == nullptr) {
os << "(Aborting thread was not attached to runtime!)\n";
} else {
- // TODO: we're aborting and the ScopedObjectAccess may attempt to acquire the mutator_lock_
- // which may block indefinitely if there's a misbehaving thread holding it exclusively.
- // The code below should be made robust to this.
- ScopedObjectAccess soa(self);
os << "Aborting thread:\n";
- self->Dump(os);
- if (self->IsExceptionPending()) {
- ThrowLocation throw_location;
- mirror::Throwable* exception = self->GetException(&throw_location);
- os << "Pending exception " << PrettyTypeOf(exception)
- << " thrown by '" << throw_location.Dump() << "'\n"
- << exception->Dump();
+ if (Locks::mutator_lock_->IsExclusiveHeld(self) || Locks::mutator_lock_->IsSharedHeld(self)) {
+ DumpThread(os, self);
+ } else {
+ if (Locks::mutator_lock_->SharedTryLock(self)) {
+ DumpThread(os, self);
+ Locks::mutator_lock_->SharedUnlock(self);
+ }
}
}
DumpAllThreads(os, self);
}
+ void DumpThread(std::ostream& os, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ self->Dump(os);
+ if (self->IsExceptionPending()) {
+ ThrowLocation throw_location;
+ mirror::Throwable* exception = self->GetException(&throw_location);
+ os << "Pending exception " << PrettyTypeOf(exception)
+ << " thrown by '" << throw_location.Dump() << "'\n"
+ << exception->Dump();
+ }
+ }
+
void DumpAllThreads(std::ostream& os, Thread* self) NO_THREAD_SAFETY_ANALYSIS {
bool tll_already_held = Locks::thread_list_lock_->IsExclusiveHeld(self);
bool ml_already_held = Locks::mutator_lock_->IsSharedHeld(self);