From e72da1c15dc273b39dcb5dd87c56d5713dbc1b37 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 1 Nov 2022 10:00:25 -0400 Subject: [PATCH] runtime: skip TestArenaCollision on failed reservation If TestArenaCollision cannot reserve the address range it expects to reserve, it currently fails somewhat mysteriously. Detect this case and skip the test. This could lead to test rot if we wind up always skipping this test, but it's not clear that there's a better answer. If the test does fail, we now also log what it thinks it reserved so the failure message is more useful in debugging any issues. Fixes #49415 Fixes #54597 Change-Id: I05cf27258c1c0a7a3ac8d147f36bf8890820d59b Reviewed-on: https://go-review.googlesource.com/c/go/+/446877 TryBot-Result: Gopher Robot Run-TryBot: Austin Clements Reviewed-by: Bryan Mills Reviewed-by: Michael Knyszek --- src/runtime/export_test.go | 13 +++++++++++-- src/runtime/malloc_test.go | 6 +++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 8e0a57987fb..bc1b3353e5a 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -503,7 +503,10 @@ func KeepNArenaHints(n int) { // MapNextArenaHint reserves a page at the next arena growth hint, // preventing the arena from growing there, and returns the range of // addresses that are no longer viable. -func MapNextArenaHint() (start, end uintptr) { +// +// This may fail to reserve memory. If it fails, it still returns the +// address range it attempted to reserve. +func MapNextArenaHint() (start, end uintptr, ok bool) { hint := mheap_.arenaHints addr := hint.addr if hint.down { @@ -512,7 +515,13 @@ func MapNextArenaHint() (start, end uintptr) { } else { start, end = addr, addr+heapArenaBytes } - sysReserve(unsafe.Pointer(addr), physPageSize) + got := sysReserve(unsafe.Pointer(addr), physPageSize) + ok = (addr == uintptr(got)) + if !ok { + // We were unable to get the requested reservation. + // Release what we did get and fail. + sysFreeOS(got, physPageSize) + } return } diff --git a/src/runtime/malloc_test.go b/src/runtime/malloc_test.go index cc2007604dd..a13f3821721 100644 --- a/src/runtime/malloc_test.go +++ b/src/runtime/malloc_test.go @@ -294,7 +294,11 @@ func TestArenaCollision(t *testing.T) { for i := 0; i < 5; i++ { // Reserve memory at the next hint so it can't be used // for the heap. - start, end := MapNextArenaHint() + start, end, ok := MapNextArenaHint() + if !ok { + t.Skipf("failed to reserve memory at next arena hint [%#x, %#x)", start, end) + } + t.Logf("reserved [%#x, %#x)", start, end) disallowed = append(disallowed, [2]uintptr{start, end}) // Allocate until the runtime tries to use the hint we // just mapped over.