mirror of https://github.com/golang/go.git
runtime: fail silently if we unwind over sigpanic into C code
If we're running C code and the code panics, the runtime will inject a call to sigpanic into the C code just like it would into Go code. However, the return PC from this sigpanic will be in C code. We used to silently abort the traceback if we didn't recognize a return PC, so this went by quietly. Now we're much louder because in general this is a bad thing. However, in this one particular case, it's fine, so if we're in cgo and are looking at the return PC of sigpanic, silence the debug output. Fixes #23576. Change-Id: I03d0c14d4e4d25b29b1f5804f5e9ccc4f742f876 Reviewed-on: https://go-review.googlesource.com/90896 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
5c2be42a68
commit
ebe38b867c
|
|
@ -481,3 +481,24 @@ func TestSigStackSwapping(t *testing.T) {
|
||||||
t.Errorf("expected %q got %v", want, got)
|
t.Errorf("expected %q got %v", want, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCgoTracebackSigpanic(t *testing.T) {
|
||||||
|
// Test unwinding over a sigpanic in C code without a C
|
||||||
|
// symbolizer. See issue #23576.
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
// On Windows if we get an exception in C code, we let
|
||||||
|
// the Windows exception handler unwind it, rather
|
||||||
|
// than injecting a sigpanic.
|
||||||
|
t.Skip("no sigpanic in C on windows")
|
||||||
|
}
|
||||||
|
t.Parallel()
|
||||||
|
got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
|
||||||
|
want := "runtime.sigpanic"
|
||||||
|
if !strings.Contains(got, want) {
|
||||||
|
t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
|
||||||
|
}
|
||||||
|
nowant := "unexpected return pc"
|
||||||
|
if strings.Contains(got, nowant) {
|
||||||
|
t.Fatalf("failure incorrectly contains %q. output:\n%s\n", nowant, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright 2018 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
|
||||||
|
|
||||||
|
// This program will crash.
|
||||||
|
// We want to test unwinding from sigpanic into C code (without a C symbolizer).
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -O0
|
||||||
|
|
||||||
|
char *pnil;
|
||||||
|
|
||||||
|
static int f1(void) {
|
||||||
|
*pnil = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
register("TracebackSigpanic", TracebackSigpanic)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TracebackSigpanic() {
|
||||||
|
C.f1()
|
||||||
|
}
|
||||||
|
|
@ -286,7 +286,15 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
|
||||||
// In that context it is okay to stop early.
|
// In that context it is okay to stop early.
|
||||||
// But if callback is set, we're doing a garbage collection and must
|
// But if callback is set, we're doing a garbage collection and must
|
||||||
// get everything, so crash loudly.
|
// get everything, so crash loudly.
|
||||||
if callback != nil || printing {
|
doPrint := printing
|
||||||
|
if doPrint && gp.m.incgo && f.entry == sigpanicPC {
|
||||||
|
// We can inject sigpanic
|
||||||
|
// calls directly into C code,
|
||||||
|
// in which case we'll see a C
|
||||||
|
// return PC. Don't complain.
|
||||||
|
doPrint = false
|
||||||
|
}
|
||||||
|
if callback != nil || doPrint {
|
||||||
print("runtime: unexpected return pc for ", funcname(f), " called from ", hex(frame.lr), "\n")
|
print("runtime: unexpected return pc for ", funcname(f), " called from ", hex(frame.lr), "\n")
|
||||||
tracebackHexdump(gp.stack, &frame, lrPtr)
|
tracebackHexdump(gp.stack, &frame, lrPtr)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue