OSDN Git Service

Check pages are readable after mprotect for SEGV_ACCERR diagnosis
authorHiroshi Yamauchi <yamauchi@google.com>
Mon, 8 Feb 2016 22:18:21 +0000 (14:18 -0800)
committerHiroshi Yamauchi <yamauchi@google.com>
Tue, 9 Feb 2016 02:05:52 +0000 (18:05 -0800)
We have a suspected mprotect issue where we see seg faults after pages
are mprotected with PROT_READ|PROT_WRITE with the SS collector on
host. This change attempts to see if earlier reads would cause faults
similarly.

Bug: 19894268

Change-Id: I041a663c6b55b747120915f73a0db5f566744ed8

runtime/gc/heap.cc
runtime/mem_map.cc
runtime/mem_map.h

index 8269f76..3c9312f 100644 (file)
@@ -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.
index 18c52e4..c908b39 100644 (file)
@@ -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
index ebd550a..3eaf576 100644 (file)
@@ -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,