]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix off-by-one error finding module for PC
authorIan Lance Taylor <iant@golang.org>
Fri, 4 Mar 2016 19:29:55 +0000 (11:29 -0800)
committerIan Lance Taylor <iant@golang.org>
Fri, 4 Mar 2016 21:06:31 +0000 (21:06 +0000)
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>
src/runtime/crash_cgo_test.go
src/runtime/panic.go
src/runtime/symtab.go
src/runtime/testdata/testprogcgo/aprof.go [new file with mode: 0644]

index 00686ee7559a8362292b85d5ff457362c090c559..2f7591a8d383ae7059b344725445e850a36f669d 100644 (file)
@@ -201,3 +201,11 @@ func TestCgoPanicDeadlock(t *testing.T) {
                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)
+       }
+}
index 10065c1803f4271dd3c04e7effb867496a5f767a..59fbc83369b447557f7373f5f2112f1495c1da25 100644 (file)
@@ -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)
 }
 
index f1df93f9e4b0c58cdd6423442dd78d3ab359af9c..cd328eb899bf5f1aba28877288f387d459d5126e 100644 (file)
@@ -277,7 +277,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 (file)
index 0000000..cf52107
--- /dev/null
@@ -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")
+}