Skip to content

Commit 85f28ed

Browse files
ianlancetayloradg
authored andcommitted
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-on: https://go-review.googlesource.com/22042 Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 2d22b84 commit 85f28ed

File tree

4 files changed

+74
-1
lines changed

4 files changed

+74
-1
lines changed

src/runtime/crash_cgo_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,11 @@ func TestCgoCheckBytes(t *testing.T) {
178178
t.Errorf("cgo check too slow: got %v, expected at most %v", d1, d2*10)
179179
}
180180
}
181+
182+
func TestCgoCCodeSIGPROF(t *testing.T) {
183+
got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
184+
want := "OK\n"
185+
if got != want {
186+
t.Errorf("expected %q got %v", want, got)
187+
}
188+
}

src/runtime/panic.go

+17
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,56 @@ import (
99
"unsafe"
1010
)
1111

12+
// Calling panic with one of the errors below will call errorString.Error
13+
// which will call mallocgc to concatenate strings. That will fail if
14+
// malloc is locked, causing a confusing error message. Throw a better
15+
// error message instead.
16+
func panicCheckMalloc(err error) {
17+
gp := getg()
18+
if gp != nil && gp.m != nil && gp.m.mallocing != 0 {
19+
throw(string(err.(errorString)))
20+
}
21+
}
22+
1223
var indexError = error(errorString("index out of range"))
1324

1425
func panicindex() {
26+
panicCheckMalloc(indexError)
1527
panic(indexError)
1628
}
1729

1830
var sliceError = error(errorString("slice bounds out of range"))
1931

2032
func panicslice() {
33+
panicCheckMalloc(sliceError)
2134
panic(sliceError)
2235
}
2336

2437
var divideError = error(errorString("integer divide by zero"))
2538

2639
func panicdivide() {
40+
panicCheckMalloc(divideError)
2741
panic(divideError)
2842
}
2943

3044
var overflowError = error(errorString("integer overflow"))
3145

3246
func panicoverflow() {
47+
panicCheckMalloc(overflowError)
3348
panic(overflowError)
3449
}
3550

3651
var floatError = error(errorString("floating point error"))
3752

3853
func panicfloat() {
54+
panicCheckMalloc(floatError)
3955
panic(floatError)
4056
}
4157

4258
var memoryError = error(errorString("invalid memory address or nil pointer dereference"))
4359

4460
func panicmem() {
61+
panicCheckMalloc(memoryError)
4562
panic(memoryError)
4663
}
4764

src/runtime/symtab.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) {
199199

200200
func findmoduledatap(pc uintptr) *moduledata {
201201
for datap := &firstmoduledata; datap != nil; datap = datap.next {
202-
if datap.minpc <= pc && pc <= datap.maxpc {
202+
if datap.minpc <= pc && pc < datap.maxpc {
203203
return datap
204204
}
205205
}
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
// Test that SIGPROF received in C code does not crash the process
8+
// looking for the C code's func pointer.
9+
10+
// The test fails when the function is the first C function.
11+
// The exported functions are the first C functions, so we use that.
12+
13+
// extern void GoNop();
14+
import "C"
15+
16+
import (
17+
"bytes"
18+
"fmt"
19+
"runtime/pprof"
20+
)
21+
22+
func init() {
23+
register("CgoCCodeSIGPROF", CgoCCodeSIGPROF)
24+
}
25+
26+
//export GoNop
27+
func GoNop() {}
28+
29+
func CgoCCodeSIGPROF() {
30+
c := make(chan bool)
31+
go func() {
32+
for {
33+
<-c
34+
for i := 0; i < 1e7; i++ {
35+
C.GoNop()
36+
}
37+
c <- true
38+
}
39+
}()
40+
41+
var buf bytes.Buffer
42+
pprof.StartCPUProfile(&buf)
43+
c <- true
44+
<-c
45+
pprof.StopCPUProfile()
46+
47+
fmt.Println("OK")
48+
}

0 commit comments

Comments
 (0)