mirror of
https://github.com/golang/go
synced 2024-11-19 16:04:48 -07:00
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>
This commit is contained in:
parent
afd835434c
commit
1716162a9a
@ -201,3 +201,11 @@ func TestCgoPanicDeadlock(t *testing.T) {
|
|||||||
t.Fatalf("output does not start with %q:\n%s", want, got)
|
t.Fatalf("output does not start with %q:\n%s", want, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCgoCCodeSIGPROF(t *testing.T) {
|
||||||
|
got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
|
||||||
|
want := "OK\n"
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("expected %q got %v", want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,39 +9,56 @@ import (
|
|||||||
"unsafe"
|
"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"))
|
var indexError = error(errorString("index out of range"))
|
||||||
|
|
||||||
func panicindex() {
|
func panicindex() {
|
||||||
|
panicCheckMalloc(indexError)
|
||||||
panic(indexError)
|
panic(indexError)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sliceError = error(errorString("slice bounds out of range"))
|
var sliceError = error(errorString("slice bounds out of range"))
|
||||||
|
|
||||||
func panicslice() {
|
func panicslice() {
|
||||||
|
panicCheckMalloc(sliceError)
|
||||||
panic(sliceError)
|
panic(sliceError)
|
||||||
}
|
}
|
||||||
|
|
||||||
var divideError = error(errorString("integer divide by zero"))
|
var divideError = error(errorString("integer divide by zero"))
|
||||||
|
|
||||||
func panicdivide() {
|
func panicdivide() {
|
||||||
|
panicCheckMalloc(divideError)
|
||||||
panic(divideError)
|
panic(divideError)
|
||||||
}
|
}
|
||||||
|
|
||||||
var overflowError = error(errorString("integer overflow"))
|
var overflowError = error(errorString("integer overflow"))
|
||||||
|
|
||||||
func panicoverflow() {
|
func panicoverflow() {
|
||||||
|
panicCheckMalloc(overflowError)
|
||||||
panic(overflowError)
|
panic(overflowError)
|
||||||
}
|
}
|
||||||
|
|
||||||
var floatError = error(errorString("floating point error"))
|
var floatError = error(errorString("floating point error"))
|
||||||
|
|
||||||
func panicfloat() {
|
func panicfloat() {
|
||||||
|
panicCheckMalloc(floatError)
|
||||||
panic(floatError)
|
panic(floatError)
|
||||||
}
|
}
|
||||||
|
|
||||||
var memoryError = error(errorString("invalid memory address or nil pointer dereference"))
|
var memoryError = error(errorString("invalid memory address or nil pointer dereference"))
|
||||||
|
|
||||||
func panicmem() {
|
func panicmem() {
|
||||||
|
panicCheckMalloc(memoryError)
|
||||||
panic(memoryError)
|
panic(memoryError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) {
|
|||||||
|
|
||||||
func findmoduledatap(pc uintptr) *moduledata {
|
func findmoduledatap(pc uintptr) *moduledata {
|
||||||
for datap := &firstmoduledata; datap != nil; datap = datap.next {
|
for datap := &firstmoduledata; datap != nil; datap = datap.next {
|
||||||
if datap.minpc <= pc && pc <= datap.maxpc {
|
if datap.minpc <= pc && pc < datap.maxpc {
|
||||||
return datap
|
return datap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
48
src/runtime/testdata/testprogcgo/aprof.go
vendored
Normal file
48
src/runtime/testdata/testprogcgo/aprof.go
vendored
Normal file
@ -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")
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user