mirror of
https://github.com/golang/go
synced 2024-09-29 21:24:30 -06:00
runtime: resolve caller funcInfo after processing current frame
Currently, gentraceback resolves the funcInfo of the caller prior to processing the current frame (calling the callback, printing it, etc). As a result, if this lookup fails in a verbose context, it will print the failure before printing the frame that it's already resolved. To fix this, move the resolution of LR to a funcInfo to after current frame processing. This also has the advantage that we can reduce the scope of "flr" (the caller's funcInfo) to only the post-frame part of the loop, which will make it easier to stack-rip gentraceback into an iterator. For #54466. Change-Id: I8be44d4eac598a686c32936ab37018b8aa97c00b Reviewed-on: https://go-review.googlesource.com/c/go/+/458217 TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Felix Geisendörfer <felix.geisendoerfer@datadoghq.com>
This commit is contained in:
parent
5acd2d658e
commit
6f22d42c74
@ -202,11 +202,10 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
|
||||
frame.fp += goarch.PtrSize
|
||||
}
|
||||
}
|
||||
var flr funcInfo
|
||||
var lrPtr uintptr
|
||||
if flag&funcFlag_TOPFRAME != 0 {
|
||||
// This function marks the top of the stack. Stop the traceback.
|
||||
frame.lr = 0
|
||||
flr = funcInfo{}
|
||||
} else if flag&funcFlag_SPWRITE != 0 && (callback == nil || n > 0) {
|
||||
// The function we are in does a write to SP that we don't know
|
||||
// how to encode in the spdelta table. Examples include context
|
||||
@ -230,9 +229,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
|
||||
throw("traceback")
|
||||
}
|
||||
frame.lr = 0
|
||||
flr = funcInfo{}
|
||||
} else {
|
||||
var lrPtr uintptr
|
||||
if usesLR {
|
||||
if n == 0 && frame.sp < frame.fp || frame.lr == 0 {
|
||||
lrPtr = frame.sp
|
||||
@ -244,28 +241,6 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
|
||||
frame.lr = uintptr(*(*uintptr)(unsafe.Pointer(lrPtr)))
|
||||
}
|
||||
}
|
||||
flr = findfunc(frame.lr)
|
||||
if !flr.valid() {
|
||||
// This happens if you get a profiling interrupt at just the wrong time.
|
||||
// In that context it is okay to stop early.
|
||||
// But if callback is set, we're doing a garbage collection and must
|
||||
// get everything, so crash loudly.
|
||||
doPrint := printing
|
||||
if doPrint && gp.m.incgo && f.funcID == funcID_sigpanic {
|
||||
// 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: g ", gp.goid, ": unexpected return pc for ", funcname(f), " called from ", hex(frame.lr), "\n")
|
||||
tracebackHexdump(gp.stack, &frame, lrPtr)
|
||||
}
|
||||
if callback != nil {
|
||||
throw("unknown caller pc")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frame.varp = frame.fp
|
||||
@ -469,7 +444,30 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
|
||||
injectedCall := f.funcID == funcID_sigpanic || f.funcID == funcID_asyncPreempt || f.funcID == funcID_debugCallV2
|
||||
|
||||
// Do not unwind past the bottom of the stack.
|
||||
if frame.lr == 0 {
|
||||
break
|
||||
}
|
||||
flr := findfunc(frame.lr)
|
||||
if !flr.valid() {
|
||||
// This happens if you get a profiling interrupt at just the wrong time.
|
||||
// In that context it is okay to stop early.
|
||||
// But if callback is set, we're doing a garbage collection and must
|
||||
// get everything, so crash loudly.
|
||||
doPrint := printing
|
||||
if doPrint && gp.m.incgo && f.funcID == funcID_sigpanic {
|
||||
// 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: g ", gp.goid, ": unexpected return pc for ", funcname(f), " called from ", hex(frame.lr), "\n")
|
||||
tracebackHexdump(gp.stack, &frame, lrPtr)
|
||||
}
|
||||
if callback != nil {
|
||||
throw("unknown caller pc")
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user