aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/traceback.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/traceback.go')
-rw-r--r--src/runtime/traceback.go48
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")