[boehm] Avoid a ENOMEM when allocating across an unallocated page
authorGeoff Norton <grompf@sublimeintervention.com>
Fri, 29 Apr 2011 20:23:15 +0000 (16:23 -0400)
committerGeoff Norton <grompf@sublimeintervention.com>
Fri, 29 Apr 2011 20:34:27 +0000 (16:34 -0400)
A very rare allocation pattern could cause the boehm free list to call
the GC_unmap_gap function, which actually calls down into munmap().
Darwins virtual memory manager will return a KERN_INVALID_ADDRESS
which is translated into a ENOMEM, if mprotect attempts to change
the protection of a range which includes an unallocated page.
We address this by just mmap() back to ANON, instead of actually
unallocating the page.

libgc/os_dep.c

index ecaa27c7d825318756c853bba76ca0e82d6e19ed..8c8e0981dd6e236f531abd538290c5cd11865bed 100644 (file)
@@ -2131,7 +2131,14 @@ void GC_unmap_gap(ptr_t start1, word bytes1, ptr_t start2, word bytes2)
          len -= free_len;
       }
 #   else
-      if (len != 0 && munmap(start_addr, len) != 0) ABORT("munmap failed");
+      if (len != 0) {
+        /* Immediately remap as above. */
+        void * result;
+        result = mmap(start_addr, len, PROT_NONE,
+                      MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
+                      zero_fd, 0/* offset */);
+        if (result != (void *)start_addr) ABORT("mmap(...PROT_NONE...) failed");
+      }
       GC_unmapped_bytes += len;
 #   endif
 }