diff --git a/error.go b/error.go index 5eb53265a..b9ae9e4c6 100644 --- a/error.go +++ b/error.go @@ -309,7 +309,7 @@ func initStacktrace(e *Error, err error) { for i, frame := range stackTrace { pc[i] = uintptr(frame) } - e.stacktrace = stacktrace.AppendCallerFrames(e.stacktrace[:0], pc) + e.stacktrace = stacktrace.AppendCallerFrames(e.stacktrace[:0], pc, -1) } } diff --git a/stacktrace/stacktrace.go b/stacktrace/stacktrace.go index ab1ce1d2a..9e5825523 100644 --- a/stacktrace/stacktrace.go +++ b/stacktrace/stacktrace.go @@ -27,7 +27,7 @@ func AppendStacktrace(frames []Frame, skip, n int) []Frame { pc = pc[:runtime.Callers(skip+1, pc)] } else { // n is negative, get all frames. - n = 0 + n := 0 pc = make([]uintptr, 10) for { n += runtime.Callers(skip+n+1, pc[n:]) @@ -38,19 +38,21 @@ func AppendStacktrace(frames []Frame, skip, n int) []Frame { pc = append(pc, 0) } } - return AppendCallerFrames(frames, pc) + return AppendCallerFrames(frames, pc, n) } -// AppendCallerFrames appends to frames for the PCs in callers, -// and returns the extended slice. +// AppendCallerFrames appends to n frames for the PCs in callers, +// and returns the extended slice. If n is negative, all available +// frames will be added. Multiple frames may exist for the same +// caller/PC in the case of function call inlining. // // See RuntimeFrame for information on what details are included. -func AppendCallerFrames(frames []Frame, callers []uintptr) []Frame { +func AppendCallerFrames(frames []Frame, callers []uintptr, n int) []Frame { if len(callers) == 0 { return frames } runtimeFrames := runtime.CallersFrames(callers) - for { + for i := 0; n < 0 || i < n; i++ { runtimeFrame, more := runtimeFrames.Next() frames = append(frames, RuntimeFrame(runtimeFrame)) if !more {