Avoid accessing the heap without mutator lock in Monitor::Lock.
ScopedThreadStateTransition doesn't do annotations and we are
accidentally accessing the heap without holding the mutator lock in
Monitor::PrettyContentionInfo. Use ScopedThreadSuspension instead.
Bug: 34674595
Test: test-art-host
Change-Id: If3ec86429ff99405ab14b3588f192ab1c0472cc8
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 071b0e2..0ceb23a 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -303,6 +303,7 @@
ArtMethod* owners_method,
uint32_t owners_dex_pc,
size_t num_waiters) {
+ Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
const char* owners_filename;
int32_t owners_line_number = 0;
if (owners_method != nullptr) {
@@ -359,7 +360,7 @@
self->SetMonitorEnterObject(GetObject());
{
uint32_t original_owner_thread_id = 0u;
- ScopedThreadStateChange tsc(self, kBlocked); // Change to blocked and give up mutator_lock_.
+ ScopedThreadSuspension tsc(self, kBlocked); // Change to blocked and give up mutator_lock_.
{
// Reacquire monitor_lock_ without mutator_lock_ for Wait.
MutexLock mu2(self, monitor_lock_);
@@ -367,22 +368,26 @@
original_owner_thread_id = owner_->GetThreadId();
if (ATRACE_ENABLED()) {
std::ostringstream oss;
- std::string name;
- owner_->GetThreadName(name);
- oss << PrettyContentionInfo(name,
- owner_->GetTid(),
- owners_method,
- owners_dex_pc,
- num_waiters);
- // Add info for contending thread.
- uint32_t pc;
- ArtMethod* m = self->GetCurrentMethod(&pc);
- const char* filename;
- int32_t line_number;
- TranslateLocation(m, pc, &filename, &line_number);
- oss << " blocking from "
- << ArtMethod::PrettyMethod(m) << "(" << (filename != nullptr ? filename : "null")
- << ":" << line_number << ")";
+ {
+ // Reacquire mutator_lock_ for getting the location info.
+ ScopedObjectAccess soa(self);
+ std::string name;
+ owner_->GetThreadName(name);
+ oss << PrettyContentionInfo(name,
+ owner_->GetTid(),
+ owners_method,
+ owners_dex_pc,
+ num_waiters);
+ // Add info for contending thread.
+ uint32_t pc;
+ ArtMethod* m = self->GetCurrentMethod(&pc);
+ const char* filename;
+ int32_t line_number;
+ TranslateLocation(m, pc, &filename, &line_number);
+ oss << " blocking from "
+ << ArtMethod::PrettyMethod(m) << "(" << (filename != nullptr ? filename : "null")
+ << ":" << line_number << ")";
+ }
ATRACE_BEGIN(oss.str().c_str());
}
monitor_contenders_.Wait(self); // Still contended so wait.
@@ -414,6 +419,8 @@
sample_percent = 100 * wait_ms / lock_profiling_threshold_;
}
if (sample_percent != 0 && (static_cast<uint32_t>(rand() % 100) < sample_percent)) {
+ // Reacquire mutator_lock_ for logging.
+ ScopedObjectAccess soa(self);
if (wait_ms > kLongWaitMs && owners_method != nullptr) {
uint32_t pc;
ArtMethod* m = self->GetCurrentMethod(&pc);