Skip to content

Commit 86f6bf1

Browse files
committed
runtime: handle async fatal signals in VDSO
If we receive an async signal while running in the VDSO, such as a SIGABRT or SIGSEGV sent from another process, we fail to print the stacktrace with "runtime: unknown pc <vdso PC>". We already have machinery to handle SIGPROF in the VDSO, but it isn't hooked up for other signals. Add it to the general signal traceback path. This case is covered by TestSegv by making the test more strict w.r.t. accepted output. Fixes #47537 Change-Id: I755585f70e0c23e207e135bc6bd2aa68298e5d24 Reviewed-on: https://go-review.googlesource.com/c/go/+/339990 Trust: Michael Pratt <[email protected]> Run-TryBot: Michael Pratt <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Cherry Mui <[email protected]>
1 parent 091db63 commit 86f6bf1

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed

src/runtime/crash_cgo_test.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -526,13 +526,15 @@ func TestCgoTracebackSigpanic(t *testing.T) {
526526
}
527527
t.Parallel()
528528
got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
529+
t.Log(got)
529530
want := "runtime.sigpanic"
530531
if !strings.Contains(got, want) {
531-
t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
532+
t.Errorf("did not see %q in output", want)
532533
}
533-
nowant := "unexpected return pc"
534+
// No runtime errors like "runtime: unexpected return pc".
535+
nowant := "runtime: "
534536
if strings.Contains(got, nowant) {
535-
t.Fatalf("failure incorrectly contains %q. output:\n%s\n", nowant, got)
537+
t.Errorf("unexpectedly saw %q in output", want)
536538
}
537539
}
538540

@@ -619,8 +621,14 @@ func TestSegv(t *testing.T) {
619621
t.Parallel()
620622
got := runTestProg(t, "testprogcgo", test)
621623
t.Log(got)
622-
if !strings.Contains(got, "SIGSEGV") {
623-
t.Errorf("expected crash from signal")
624+
want := "SIGSEGV"
625+
if !strings.Contains(got, want) {
626+
t.Errorf("did not see %q in output", want)
627+
}
628+
// No runtime errors like "runtime: unknown pc".
629+
nowant := "runtime: "
630+
if strings.Contains(got, nowant) {
631+
t.Errorf("unexpectedly saw %q in output", want)
624632
}
625633
})
626634
}

src/runtime/traceback.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,16 +777,23 @@ func traceback1(pc, sp, lr uintptr, gp *g, flags uint) {
777777
printCgoTraceback(&cgoCallers)
778778
}
779779

780-
var n int
781780
if readgstatus(gp)&^_Gscan == _Gsyscall {
782781
// Override registers if blocked in system call.
783782
pc = gp.syscallpc
784783
sp = gp.syscallsp
785784
flags &^= _TraceTrap
786785
}
786+
if gp.m != nil && gp.m.vdsoSP != 0 {
787+
// Override registers if running in VDSO. This comes after the
788+
// _Gsyscall check to cover VDSO calls after entersyscall.
789+
pc = gp.m.vdsoPC
790+
sp = gp.m.vdsoSP
791+
flags &^= _TraceTrap
792+
}
793+
787794
// Print traceback. By default, omits runtime frames.
788795
// If that means we print nothing at all, repeat forcing all frames printed.
789-
n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags)
796+
n := gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags)
790797
if n == 0 && (flags&_TraceRuntimeFrames) == 0 {
791798
n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags|_TraceRuntimeFrames)
792799
}

0 commit comments

Comments
 (0)