]> 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)
committerAndrew Gerrand <adg@golang.org>
Thu, 14 Apr 2016 05:23:37 +0000 (05:23 +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>
Reviewed-on: https://go-review.googlesource.com/22042
Reviewed-by: Ian Lance Taylor <iant@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 7685582aa8ad9485f527cf07ac71aed807ce72a0..d07a92ffb2589d8e527924499cc6b26ae933861b 100644 (file)
@@ -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)
+       }
+}
index ba07330e35c4e51e5078fb0b422011f57066f804..3d9d0359660653ef6232d71fa8ab3706a13e1cef 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 00b0a850e0d4635239d1112f717243238bd6d2a9..6e02f1e6e9a96f402954b9e4107e86e9e978daa8 100644 (file)
@@ -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 (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")
+}