Skip to content

Commit a0c9d15

Browse files
committed
runtime: don't inject a sigpanic if not on user G stack
If a panicking signal (e.g. SIGSEGV) happens on a g0 stack, we're either in the runtime or running C code. Either way we cannot recover and sigpanic will immediately throw. Further, injecting a sigpanic could make the C stack unwinder and the debugger fail to unwind the stack. So don't inject a sigpanic. If we have cgo traceback and symbolizer attached, if it panics in a C function ("CF" for the example below), previously it shows something like fatal error: unexpected signal during runtime execution [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x45f1ef] runtime stack: runtime.throw({0x485460?, 0x0?}) .../runtime/panic.go:1076 +0x5c fp=0x7ffd77f60f58 sp=0x7ffd77f60f28 pc=0x42e39c runtime.sigpanic() .../runtime/signal_unix.go:821 +0x3e9 fp=0x7ffd77f60fb8 sp=0x7ffd77f60f58 pc=0x442229 goroutine 1 [syscall]: CF /tmp/pp/c.c:6 pc=0x45f1ef runtime.asmcgocall .../runtime/asm_amd64.s:869 pc=0x458007 runtime.cgocall(0x45f1d0, 0xc000053f70) .../runtime/cgocall.go:158 +0x51 fp=0xc000053f48 sp=0xc000053f10 pc=0x404551 main._Cfunc_CF() _cgo_gotypes.go:39 +0x3f fp=0xc000053f70 sp=0xc000053f48 pc=0x45f0bf Now it shows SIGSEGV: segmentation violation PC=0x45f1ef m=0 sigcode=1 signal arrived during cgo execution goroutine 1 [syscall]: CF /tmp/pp/c.c:6 pc=0x45f1ef runtime.asmcgocall .../runtime/asm_amd64.s:869 pc=0x458007 runtime.cgocall(0x45f1d0, 0xc00004ef70) .../runtime/cgocall.go:158 +0x51 fp=0xc00004ef48 sp=0xc00004ef10 pc=0x404551 main._Cfunc_CF() _cgo_gotypes.go:39 +0x3f fp=0xc00004ef70 sp=0xc00004ef48 pc=0x45f0bf I think the new one is reasonable. For #57698. Change-Id: I4f7af91761374e9b569dce4c7587499d4799137e Reviewed-on: https://go-review.googlesource.com/c/go/+/462437 Reviewed-by: Michael Pratt <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Cherry Mui <[email protected]>
1 parent 06264b7 commit a0c9d15

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

src/runtime/crash_cgo_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,15 +518,21 @@ func TestCgoTracebackSigpanic(t *testing.T) {
518518
t.Parallel()
519519
got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
520520
t.Log(got)
521-
want := "runtime.sigpanic"
521+
// We should see the function that calls the C function.
522+
want := "main.TracebackSigpanic"
522523
if !strings.Contains(got, want) {
523524
if runtime.GOOS == "android" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
524525
testenv.SkipFlaky(t, 58794)
525526
}
526527
t.Errorf("did not see %q in output", want)
527528
}
529+
// We shouldn't inject a sigpanic call. (see issue 57698)
530+
nowant := "runtime.sigpanic"
531+
if strings.Contains(got, nowant) {
532+
t.Errorf("unexpectedly saw %q in output", nowant)
533+
}
528534
// No runtime errors like "runtime: unexpected return pc".
529-
nowant := "runtime: "
535+
nowant = "runtime: "
530536
if strings.Contains(got, nowant) {
531537
t.Errorf("unexpectedly saw %q in output", nowant)
532538
}

src/runtime/signal_unix.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,13 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
673673
if sig < uint32(len(sigtable)) {
674674
flags = sigtable[sig].flags
675675
}
676-
if !c.sigFromUser() && flags&_SigPanic != 0 && gp.throwsplit {
676+
if !c.sigFromUser() && flags&_SigPanic != 0 && (gp.throwsplit || gp != mp.curg) {
677677
// We can't safely sigpanic because it may grow the
678678
// stack. Abort in the signal handler instead.
679+
//
680+
// Also don't inject a sigpanic if we are not on a
681+
// user G stack. Either we're in the runtime, or we're
682+
// running C code. Either way we cannot recover.
679683
flags = _SigThrow
680684
}
681685
if isAbortPC(c.sigpc()) {

0 commit comments

Comments
 (0)