mirror of
https://github.com/golang/go
synced 2024-11-17 08:14:48 -07:00
runtime: fix callee tracking in traceback printing
In CL 466099, we accidentally stopped tracking callees while unwinding inlined frames during traceback printing. The effect is that if you have a call stack like: f -> wrapper -> inlined into wrapper -> panic when considering whether to print the frame for "wrapper", we'll think that wrapper called panic, rather than the inlined function. Fix this in the traceback code and add a test. Change-Id: I30ec836cc316846ce93de94e28a650e23dca184e Reviewed-on: https://go-review.googlesource.com/c/go/+/476579 Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
parent
be27fcfd2b
commit
5f62ba621e
@ -6,6 +6,7 @@ package runtime_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"reflect"
|
||||
"regexp"
|
||||
. "runtime"
|
||||
@ -652,6 +653,8 @@ func (s structWithMethod) stack() string {
|
||||
|
||||
func (s structWithMethod) nop() {}
|
||||
|
||||
func (s structWithMethod) inlinablePanic() { panic("panic") }
|
||||
|
||||
func TestStackWrapperCaller(t *testing.T) {
|
||||
var d structWithMethod
|
||||
// Force the compiler to construct a wrapper method.
|
||||
@ -689,6 +692,33 @@ func TestStackWrapperStack(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStackWrapperStackInlinePanic(t *testing.T) {
|
||||
// Test that inline unwinding correctly tracks the callee by creating a
|
||||
// stack of the form wrapper -> inlined function -> panic. If we mess up
|
||||
// callee tracking, it will look like the wrapper called panic and we'll see
|
||||
// the wrapper in the stack trace.
|
||||
var d structWithMethod
|
||||
wrapper := (*structWithMethod).inlinablePanic
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
t.Fatalf("expected panic")
|
||||
}
|
||||
buf := make([]byte, 4<<10)
|
||||
stk := string(buf[:Stack(buf, false)])
|
||||
if strings.Contains(stk, "<autogenerated>") {
|
||||
t.Fatalf("<autogenerated> appears in stack trace:\n%s", stk)
|
||||
}
|
||||
// Self-check: make sure inlinablePanic got inlined.
|
||||
if !testenv.OptimizationOff() {
|
||||
if !strings.Contains(stk, "inlinablePanic(...)") {
|
||||
t.Fatalf("inlinablePanic not inlined")
|
||||
}
|
||||
}
|
||||
}()
|
||||
wrapper(&d)
|
||||
}
|
||||
|
||||
type I interface {
|
||||
M()
|
||||
}
|
||||
|
@ -845,7 +845,9 @@ func traceback2(u *unwinder, showRuntime bool) int {
|
||||
f := u.frame.fn
|
||||
for iu, uf := newInlineUnwinder(f, u.symPC(), noEscapePtr(&u.cache)); n < max && uf.valid(); uf = iu.next(uf) {
|
||||
sf := iu.srcFunc(uf)
|
||||
if !(showRuntime || showframe(sf, gp, n == 0, u.calleeFuncID)) {
|
||||
callee := u.calleeFuncID
|
||||
u.calleeFuncID = sf.funcID
|
||||
if !(showRuntime || showframe(sf, gp, n == 0, callee)) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user