Skip to content

Commit 6f22d42

Browse files
committed
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 <[email protected]> Run-TryBot: Austin Clements <[email protected]> Reviewed-by: Michael Pratt <[email protected]> Reviewed-by: Felix Geisendörfer <[email protected]>
1 parent 5acd2d6 commit 6f22d42

File tree

1 file changed

+24
-26
lines changed

1 file changed

+24
-26
lines changed

src/runtime/traceback.go

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,10 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
202202
frame.fp += goarch.PtrSize
203203
}
204204
}
205-
var flr funcInfo
205+
var lrPtr uintptr
206206
if flag&funcFlag_TOPFRAME != 0 {
207207
// This function marks the top of the stack. Stop the traceback.
208208
frame.lr = 0
209-
flr = funcInfo{}
210209
} else if flag&funcFlag_SPWRITE != 0 && (callback == nil || n > 0) {
211210
// The function we are in does a write to SP that we don't know
212211
// 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
230229
throw("traceback")
231230
}
232231
frame.lr = 0
233-
flr = funcInfo{}
234232
} else {
235-
var lrPtr uintptr
236233
if usesLR {
237234
if n == 0 && frame.sp < frame.fp || frame.lr == 0 {
238235
lrPtr = frame.sp
@@ -244,28 +241,6 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
244241
frame.lr = uintptr(*(*uintptr)(unsafe.Pointer(lrPtr)))
245242
}
246243
}
247-
flr = findfunc(frame.lr)
248-
if !flr.valid() {
249-
// This happens if you get a profiling interrupt at just the wrong time.
250-
// In that context it is okay to stop early.
251-
// But if callback is set, we're doing a garbage collection and must
252-
// get everything, so crash loudly.
253-
doPrint := printing
254-
if doPrint && gp.m.incgo && f.funcID == funcID_sigpanic {
255-
// We can inject sigpanic
256-
// calls directly into C code,
257-
// in which case we'll see a C
258-
// return PC. Don't complain.
259-
doPrint = false
260-
}
261-
if callback != nil || doPrint {
262-
print("runtime: g ", gp.goid, ": unexpected return pc for ", funcname(f), " called from ", hex(frame.lr), "\n")
263-
tracebackHexdump(gp.stack, &frame, lrPtr)
264-
}
265-
if callback != nil {
266-
throw("unknown caller pc")
267-
}
268-
}
269244
}
270245

271246
frame.varp = frame.fp
@@ -469,7 +444,30 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
469444
injectedCall := f.funcID == funcID_sigpanic || f.funcID == funcID_asyncPreempt || f.funcID == funcID_debugCallV2
470445

471446
// Do not unwind past the bottom of the stack.
447+
if frame.lr == 0 {
448+
break
449+
}
450+
flr := findfunc(frame.lr)
472451
if !flr.valid() {
452+
// This happens if you get a profiling interrupt at just the wrong time.
453+
// In that context it is okay to stop early.
454+
// But if callback is set, we're doing a garbage collection and must
455+
// get everything, so crash loudly.
456+
doPrint := printing
457+
if doPrint && gp.m.incgo && f.funcID == funcID_sigpanic {
458+
// We can inject sigpanic
459+
// calls directly into C code,
460+
// in which case we'll see a C
461+
// return PC. Don't complain.
462+
doPrint = false
463+
}
464+
if callback != nil || doPrint {
465+
print("runtime: g ", gp.goid, ": unexpected return pc for ", funcname(f), " called from ", hex(frame.lr), "\n")
466+
tracebackHexdump(gp.stack, &frame, lrPtr)
467+
}
468+
if callback != nil {
469+
throw("unknown caller pc")
470+
}
473471
break
474472
}
475473

0 commit comments

Comments
 (0)