Repository navigation
Expand file tree
/
Copy pathstack.go
More file actions
82 lines (74 loc) · 1.88 KB
/
Copy pathstack.go
File metadata and controls
82 lines (74 loc) · 1.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package evs
import (
"runtime"
)
const (
startStackDepth = 10
maxStackDepth = 200
)
// Frame defines a single frame in a stack trace.
type Frame struct {
Line int
File string
Function string
}
// CurrentFrame gets the location information for the code point where this function was called from (or
// anywhere up or down the stack from there depending on the skip value given.)
func CurrentFrame(skip int) Frame {
skip++
pc, file, line, _ := runtime.Caller(skip)
function := runtime.FuncForPC(pc)
return Frame{
Line: line,
File: file,
Function: function.Name(),
}
}
// Stack contains a stack trace made up of individual frames.
type Stack struct {
Frames []Frame
}
// GetStack returns the full set of frames excluding the frames within the evs package
// assuming an appropriate value for Skip has been supplied. To get the stack excluding the
// call to [GetStack] itself (and everything beneath it), the value for skip should be 0.
func GetStack(skip int) Stack {
skip++
callerPCs := getCallerPCs(skip)
callersFrames := runtime.CallersFrames(callerPCs)
frames := []Frame{}
for {
frame, more := callersFrames.Next()
frames = append(frames, Frame{
Line: frame.Line,
File: frame.File,
Function: frame.Function,
})
// Check whether there are more frames to process after this one.
if !more {
break
}
}
return Stack{Frames: frames}
}
func getCallerPCs(skip int) []uintptr {
skip++
skip++
stackDepth := startStackDepth
callerPCs := make([]uintptr, stackDepth)
count := runtime.Callers(skip, callerPCs)
if count == 0 {
return []uintptr{}
}
for {
if count < stackDepth || stackDepth == maxStackDepth {
return callerPCs[:count]
} else {
stackDepth = stackDepth * 2
if stackDepth > maxStackDepth {
stackDepth = maxStackDepth
}
callerPCs = make([]uintptr, stackDepth)
count = runtime.Callers(skip, callerPCs)
}
}
}