summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/gc/heap.cc4
-rw-r--r--runtime/mem_map.cc18
-rw-r--r--runtime/mem_map.h5
3 files changed, 27 insertions, 0 deletions
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 8269f7662f..3c9312f256 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2622,6 +2622,10 @@ collector::GcType Heap::CollectGarbageInternal(collector::GcType gc_type,
}
if (collector != mark_compact_collector_ && collector != concurrent_copying_collector_) {
temp_space_->GetMemMap()->Protect(PROT_READ | PROT_WRITE);
+ if (kIsDebugBuild) {
+ // Try to read each page of the memory map in case mprotect didn't work properly b/19894268.
+ temp_space_->GetMemMap()->TryReadable();
+ }
CHECK(temp_space_->IsEmpty());
}
gc_type = collector::kGcTypeFull; // TODO: Not hard code this in.
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 18c52e47b6..c908b3920a 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -877,4 +877,22 @@ std::ostream& operator<<(std::ostream& os, const MemMap& mem_map) {
return os;
}
+void MemMap::TryReadable() {
+ if (base_begin_ == nullptr && base_size_ == 0) {
+ return;
+ }
+ CHECK_NE(prot_ & PROT_READ, 0);
+ volatile uint8_t* begin = reinterpret_cast<volatile uint8_t*>(base_begin_);
+ volatile uint8_t* end = begin + base_size_;
+ DCHECK(IsAligned<kPageSize>(begin));
+ DCHECK(IsAligned<kPageSize>(end));
+ // Read the first byte of each page. Use volatile to prevent the compiler from optimizing away the
+ // reads.
+ for (volatile uint8_t* ptr = begin; ptr < end; ptr += kPageSize) {
+ // This read could fault if protection wasn't set correctly.
+ uint8_t value = *ptr;
+ UNUSED(value);
+ }
+}
+
} // namespace art
diff --git a/runtime/mem_map.h b/runtime/mem_map.h
index ebd550a552..3eaf576845 100644
--- a/runtime/mem_map.h
+++ b/runtime/mem_map.h
@@ -184,6 +184,11 @@ class MemMap {
static void Init() REQUIRES(!Locks::mem_maps_lock_);
static void Shutdown() REQUIRES(!Locks::mem_maps_lock_);
+ // If the map is PROT_READ, try to read each page of the map to check it is in fact readable (not
+ // faulting). This is used to diagnose a bug b/19894268 where mprotect doesn't seem to be working
+ // intermittently.
+ void TryReadable();
+
private:
MemMap(const std::string& name,
uint8_t* begin,