diff options
Diffstat (limited to 'src/runtime/traceback.go')
| -rw-r--r-- | src/runtime/traceback.go | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index c74d438757..501ecb0411 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -184,6 +184,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in cgoCtxt := gp.cgoCtxt printing := pcbuf == nil && callback == nil _defer := gp._defer + elideWrapper := false for _defer != nil && _defer.sp == _NoArgs { _defer = _defer.link @@ -386,8 +387,15 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } if printing { - // assume skip=0 for printing - if (flags&_TraceRuntimeFrames) != 0 || showframe(f, gp, nprint == 0) { + // assume skip=0 for printing. + // + // Never elide wrappers if we haven't printed + // any frames. And don't elide wrappers that + // called panic rather than the wrapped + // function. Otherwise, leave them out. + name := funcname(f) + nextElideWrapper := elideWrapperCalling(name) + if (flags&_TraceRuntimeFrames) != 0 || showframe(f, gp, nprint == 0, elideWrapper && nprint != 0) { // Print during crash. // main(0x1, 0x2, 0x3) // /home/rsc/go/src/runtime/x.go:23 +0xf @@ -411,7 +419,6 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in ix = inltree[ix].parent } } - name := funcname(f) if name == "runtime.gopanic" { name = "panic" } @@ -438,6 +445,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in print("\n") nprint++ } + elideWrapper = nextElideWrapper } n++ @@ -647,7 +655,7 @@ func printcreatedby(gp *g) { // Show what created goroutine, except main goroutine (goid 1). pc := gp.gopc f := findfunc(pc) - if f.valid() && showframe(f, gp, false) && gp.goid != 1 { + if f.valid() && showframe(f, gp, false, false) && gp.goid != 1 { print("created by ", funcname(f), "\n") tracepc := pc // back up to CALL instruction for funcline. if pc > f.entry { @@ -714,7 +722,7 @@ func traceback1(pc, sp, lr uintptr, gp *g, flags uint) { func callers(skip int, pcbuf []uintptr) int { sp := getcallersp(unsafe.Pointer(&skip)) - pc := getcallerpc(unsafe.Pointer(&skip)) + pc := getcallerpc() gp := getg() var n int systemstack(func() { @@ -727,12 +735,28 @@ func gcallers(gp *g, skip int, pcbuf []uintptr) int { return gentraceback(^uintptr(0), ^uintptr(0), 0, gp, skip, &pcbuf[0], len(pcbuf), nil, nil, 0) } -func showframe(f funcInfo, gp *g, firstFrame bool) bool { +func showframe(f funcInfo, gp *g, firstFrame, elideWrapper bool) bool { g := getg() if g.m.throwing > 0 && gp != nil && (gp == g.m.curg || gp == g.m.caughtsig.ptr()) { return true } level, _, _ := gotraceback() + if level > 1 { + // Show all frames. + return true + } + + if !f.valid() { + return false + } + + if elideWrapper { + file, _ := funcline(f, f.entry) + if file == "<autogenerated>" { + return false + } + } + name := funcname(f) // Special case: always show runtime.gopanic frame @@ -744,7 +768,7 @@ func showframe(f funcInfo, gp *g, firstFrame bool) bool { return true } - return level > 1 || f.valid() && contains(name, ".") && (!hasprefix(name, "runtime.") || isExportedRuntime(name)) + return contains(name, ".") && (!hasprefix(name, "runtime.") || isExportedRuntime(name)) } // isExportedRuntime reports whether name is an exported runtime function. @@ -754,6 +778,14 @@ func isExportedRuntime(name string) bool { return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z' } +// elideWrapperCalling returns whether a wrapper function that called +// function "name" should be elided from stack traces. +func elideWrapperCalling(name string) bool { + // If the wrapper called a panic function instead of the + // wrapped function, we want to include it in stacks. + return !(name == "runtime.gopanic" || name == "runtime.sigpanic" || name == "runtime.panicwrap") +} + var gStatusStrings = [...]string{ _Gidle: "idle", _Grunnable: "runnable", @@ -795,7 +827,7 @@ func goroutineheader(gp *g) { if waitfor >= 1 { print(", ", waitfor, " minutes") } - if gp.lockedm != nil { + if gp.lockedm != 0 { print(", locked to thread") } print("]:\n") |
