diff options
Diffstat (limited to 'libgo/go/runtime/debug')
-rw-r--r-- | libgo/go/runtime/debug/garbage.go | 7 | ||||
-rw-r--r-- | libgo/go/runtime/debug/heapdump_test.go | 5 | ||||
-rw-r--r-- | libgo/go/runtime/debug/panic_test.go | 53 |
3 files changed, 62 insertions, 3 deletions
diff --git a/libgo/go/runtime/debug/garbage.go b/libgo/go/runtime/debug/garbage.go index 785e9d4..00f92c3 100644 --- a/libgo/go/runtime/debug/garbage.go +++ b/libgo/go/runtime/debug/garbage.go @@ -106,6 +106,8 @@ func FreeOSMemory() { // the program crashes. // SetMaxStack returns the previous setting. // The initial setting is 1 GB on 64-bit systems, 250 MB on 32-bit systems. +// There may be a system-imposed maximum stack limit regardless +// of the value provided to SetMaxStack. // // SetMaxStack is useful mainly for limiting the damage done by // goroutines that enter an infinite recursion. It only limits future @@ -139,6 +141,11 @@ func SetMaxThreads(threads int) int { // manipulation of memory may cause faults at non-nil addresses in less // dramatic situations; SetPanicOnFault allows such programs to request // that the runtime trigger only a panic, not a crash. +// The runtime.Error that the runtime panics with may have an additional method: +// Addr() uintptr +// If that method exists, it returns the memory address which triggered the fault. +// The results of Addr are best-effort and the veracity of the result +// may depend on the platform. // SetPanicOnFault applies only to the current goroutine. // It returns the previous setting. func SetPanicOnFault(enabled bool) bool { diff --git a/libgo/go/runtime/debug/heapdump_test.go b/libgo/go/runtime/debug/heapdump_test.go index de1ec27..768934d 100644 --- a/libgo/go/runtime/debug/heapdump_test.go +++ b/libgo/go/runtime/debug/heapdump_test.go @@ -5,7 +5,6 @@ package debug_test import ( - "io/ioutil" "os" "runtime" . "runtime/debug" @@ -16,7 +15,7 @@ func TestWriteHeapDumpNonempty(t *testing.T) { if runtime.GOOS == "js" { t.Skipf("WriteHeapDump is not available on %s.", runtime.GOOS) } - f, err := ioutil.TempFile("", "heapdumptest") + f, err := os.CreateTemp("", "heapdumptest") if err != nil { t.Fatalf("TempFile failed: %v", err) } @@ -45,7 +44,7 @@ func TestWriteHeapDumpFinalizers(t *testing.T) { if runtime.GOOS == "js" { t.Skipf("WriteHeapDump is not available on %s.", runtime.GOOS) } - f, err := ioutil.TempFile("", "heapdumptest") + f, err := os.CreateTemp("", "heapdumptest") if err != nil { t.Fatalf("TempFile failed: %v", err) } diff --git a/libgo/go/runtime/debug/panic_test.go b/libgo/go/runtime/debug/panic_test.go new file mode 100644 index 0000000..b67a3de --- /dev/null +++ b/libgo/go/runtime/debug/panic_test.go @@ -0,0 +1,53 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build aix darwin dragonfly freebsd linux netbsd openbsd + +// TODO: test on Windows? + +package debug_test + +import ( + "runtime" + "runtime/debug" + "syscall" + "testing" + "unsafe" +) + +func TestPanicOnFault(t *testing.T) { + if runtime.GOARCH == "s390x" { + t.Skip("s390x fault addresses are missing the low order bits") + } + if runtime.GOOS == "ios" { + t.Skip("iOS doesn't provide fault addresses") + } + m, err := syscall.Mmap(-1, 0, 0x1000, syscall.PROT_READ /* Note: no PROT_WRITE */, syscall.MAP_SHARED|syscall.MAP_ANON) + if err != nil { + t.Fatalf("can't map anonymous memory: %s", err) + } + defer syscall.Munmap(m) + old := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(old) + const lowBits = 0x3e7 + defer func() { + r := recover() + if r == nil { + t.Fatalf("write did not fault") + } + type addressable interface { + Addr() uintptr + } + a, ok := r.(addressable) + if !ok { + t.Fatalf("fault does not contain address") + } + want := uintptr(unsafe.Pointer(&m[lowBits])) + got := a.Addr() + if got != want { + t.Fatalf("fault address %x, want %x", got, want) + } + }() + m[lowBits] = 1 // will fault +} |