diff options
author | Ian Lance Taylor <iant@golang.org> | 2016-03-04 11:29:55 -0800 |
---|---|---|
committer | Andrew Gerrand <adg@golang.org> | 2016-04-14 05:23:37 +0000 |
commit | 85f28edd58581554b4250b769d2a0bc805be6fb2 (patch) | |
tree | 3066882f67897210ddedb7d5673b6045113c34ee /src | |
parent | 2d22b845d92212071d698264f2445e957ff1106f (diff) | |
download | go-git-85f28edd58581554b4250b769d2a0bc805be6fb2.tar.gz |
runtime: fix off-by-one error finding module for PC
Also fix compiler-invoked panics to avoid a confusing "malloc deadlock"
crash if they are invoked while executing the runtime.
Fixes #14599.
Change-Id: I89436abcbf3587901909abbdca1973301654a76e
Reviewed-on: https://go-review.googlesource.com/20219
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-on: https://go-review.googlesource.com/22042
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/runtime/crash_cgo_test.go | 8 | ||||
-rw-r--r-- | src/runtime/panic.go | 17 | ||||
-rw-r--r-- | src/runtime/symtab.go | 2 | ||||
-rw-r--r-- | src/runtime/testdata/testprogcgo/aprof.go | 48 |
4 files changed, 74 insertions, 1 deletions
diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index 7685582aa8..d07a92ffb2 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -178,3 +178,11 @@ func TestCgoCheckBytes(t *testing.T) { t.Errorf("cgo check too slow: got %v, expected at most %v", d1, d2*10) } } + +func TestCgoCCodeSIGPROF(t *testing.T) { + got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF") + want := "OK\n" + if got != want { + t.Errorf("expected %q got %v", want, got) + } +} diff --git a/src/runtime/panic.go b/src/runtime/panic.go index ba07330e35..3d9d035966 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -9,39 +9,56 @@ import ( "unsafe" ) +// Calling panic with one of the errors below will call errorString.Error +// which will call mallocgc to concatenate strings. That will fail if +// malloc is locked, causing a confusing error message. Throw a better +// error message instead. +func panicCheckMalloc(err error) { + gp := getg() + if gp != nil && gp.m != nil && gp.m.mallocing != 0 { + throw(string(err.(errorString))) + } +} + var indexError = error(errorString("index out of range")) func panicindex() { + panicCheckMalloc(indexError) panic(indexError) } var sliceError = error(errorString("slice bounds out of range")) func panicslice() { + panicCheckMalloc(sliceError) panic(sliceError) } var divideError = error(errorString("integer divide by zero")) func panicdivide() { + panicCheckMalloc(divideError) panic(divideError) } var overflowError = error(errorString("integer overflow")) func panicoverflow() { + panicCheckMalloc(overflowError) panic(overflowError) } var floatError = error(errorString("floating point error")) func panicfloat() { + panicCheckMalloc(floatError) panic(floatError) } var memoryError = error(errorString("invalid memory address or nil pointer dereference")) func panicmem() { + panicCheckMalloc(memoryError) panic(memoryError) } diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 00b0a850e0..6e02f1e6e9 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -199,7 +199,7 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) { func findmoduledatap(pc uintptr) *moduledata { for datap := &firstmoduledata; datap != nil; datap = datap.next { - if datap.minpc <= pc && pc <= datap.maxpc { + if datap.minpc <= pc && pc < datap.maxpc { return datap } } diff --git a/src/runtime/testdata/testprogcgo/aprof.go b/src/runtime/testdata/testprogcgo/aprof.go new file mode 100644 index 0000000000..cf52107a30 --- /dev/null +++ b/src/runtime/testdata/testprogcgo/aprof.go @@ -0,0 +1,48 @@ +// Copyright 2016 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. + +package main + +// Test that SIGPROF received in C code does not crash the process +// looking for the C code's func pointer. + +// The test fails when the function is the first C function. +// The exported functions are the first C functions, so we use that. + +// extern void GoNop(); +import "C" + +import ( + "bytes" + "fmt" + "runtime/pprof" +) + +func init() { + register("CgoCCodeSIGPROF", CgoCCodeSIGPROF) +} + +//export GoNop +func GoNop() {} + +func CgoCCodeSIGPROF() { + c := make(chan bool) + go func() { + for { + <-c + for i := 0; i < 1e7; i++ { + C.GoNop() + } + c <- true + } + }() + + var buf bytes.Buffer + pprof.StartCPUProfile(&buf) + c <- true + <-c + pprof.StopCPUProfile() + + fmt.Println("OK") +} |