Skip to content

Commit 565c8d0

Browse files
authored
Merge pull request pkg#193 from pkg/fixedbugs/188
Return errors.Frame to a uintptr
2 parents 72fa05e + e9933c1 commit 565c8d0

File tree

3 files changed

+58
-40
lines changed

3 files changed

+58
-40
lines changed

format_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ func TestFormatWrappedNew(t *testing.T) {
385385
}
386386

387387
func testFormatRegexp(t *testing.T, n int, arg interface{}, format, want string) {
388+
t.Helper()
388389
got := fmt.Sprintf(format, arg)
389390
gotLines := strings.SplitN(got, "\n", -1)
390391
wantLines := strings.SplitN(want, "\n", -1)

stack.go

+51-34
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,42 @@ import (
1111
)
1212

1313
// Frame represents a program counter inside a stack frame.
14-
type Frame runtime.Frame
14+
type Frame uintptr
15+
16+
// pc returns the program counter for this frame;
17+
// multiple frames may have the same PC value.
18+
func (f Frame) pc() uintptr { return uintptr(f) - 1 }
19+
20+
// file returns the full path to the file that contains the
21+
// function for this Frame's pc.
22+
func (f Frame) file() string {
23+
fn := runtime.FuncForPC(f.pc())
24+
if fn == nil {
25+
return "unknown"
26+
}
27+
file, _ := fn.FileLine(f.pc())
28+
return file
29+
}
30+
31+
// line returns the line number of source code of the
32+
// function for this Frame's pc.
33+
func (f Frame) line() int {
34+
fn := runtime.FuncForPC(f.pc())
35+
if fn == nil {
36+
return 0
37+
}
38+
_, line := fn.FileLine(f.pc())
39+
return line
40+
}
41+
42+
// name returns the name of this function, if known.
43+
func (f Frame) name() string {
44+
fn := runtime.FuncForPC(f.pc())
45+
if fn == nil {
46+
return "unknown"
47+
}
48+
return fn.Name()
49+
}
1550

1651
// Format formats the frame according to the fmt.Formatter interface.
1752
//
@@ -35,25 +70,16 @@ func (f Frame) format(w io.Writer, s fmt.State, verb rune) {
3570
case 's':
3671
switch {
3772
case s.Flag('+'):
38-
if f.Function == "" {
39-
io.WriteString(w, "unknown")
40-
} else {
41-
io.WriteString(w, f.Function)
42-
io.WriteString(w, "\n\t")
43-
io.WriteString(w, f.File)
44-
}
73+
io.WriteString(w, f.name())
74+
io.WriteString(w, "\n\t")
75+
io.WriteString(w, f.file())
4576
default:
46-
file := f.File
47-
if file == "" {
48-
file = "unknown"
49-
}
50-
io.WriteString(w, path.Base(file))
77+
io.WriteString(w, path.Base(f.file()))
5178
}
5279
case 'd':
53-
io.WriteString(w, strconv.Itoa(f.Line))
80+
io.WriteString(w, strconv.Itoa(f.line()))
5481
case 'n':
55-
name := f.Function
56-
io.WriteString(s, funcname(name))
82+
io.WriteString(w, funcname(f.name()))
5783
case 'v':
5884
f.format(w, s, 's')
5985
io.WriteString(w, ":")
@@ -79,9 +105,9 @@ func (st StackTrace) Format(s fmt.State, verb rune) {
79105
switch {
80106
case s.Flag('+'):
81107
b.Grow(len(st) * stackMinLen)
82-
for _, fr := range st {
108+
for _, f := range st {
83109
b.WriteByte('\n')
84-
fr.format(&b, s, verb)
110+
f.format(&b, s, verb)
85111
}
86112
case s.Flag('#'):
87113
fmt.Fprintf(&b, "%#v", []Frame(st))
@@ -125,29 +151,20 @@ func (s *stack) Format(st fmt.State, verb rune) {
125151
case 'v':
126152
switch {
127153
case st.Flag('+'):
128-
frames := runtime.CallersFrames(*s)
129-
for {
130-
frame, more := frames.Next()
131-
fmt.Fprintf(st, "\n%+v", Frame(frame))
132-
if !more {
133-
break
134-
}
154+
for _, pc := range *s {
155+
f := Frame(pc)
156+
fmt.Fprintf(st, "\n%+v", f)
135157
}
136158
}
137159
}
138160
}
139161

140162
func (s *stack) StackTrace() StackTrace {
141-
var st []Frame
142-
frames := runtime.CallersFrames(*s)
143-
for {
144-
frame, more := frames.Next()
145-
st = append(st, Frame(frame))
146-
if !more {
147-
break
148-
}
163+
f := make([]Frame, len(*s))
164+
for i := 0; i < len(f); i++ {
165+
f[i] = Frame((*s)[i])
149166
}
150-
return st
167+
return f
151168
}
152169

153170
func callers() *stack {

stack_test.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,19 @@ func TestFrameFormat(t *testing.T) {
3535
"github.com/pkg/errors.init\n" +
3636
"\t.+/github.com/pkg/errors/stack_test.go",
3737
}, {
38-
Frame{},
38+
0,
3939
"%s",
4040
"unknown",
4141
}, {
42-
Frame{},
42+
0,
4343
"%+s",
4444
"unknown",
4545
}, {
4646
initpc,
4747
"%d",
4848
"9",
4949
}, {
50-
Frame{},
50+
0,
5151
"%d",
5252
"0",
5353
}, {
@@ -69,7 +69,7 @@ func TestFrameFormat(t *testing.T) {
6969
"%n",
7070
"X.val",
7171
}, {
72-
Frame{},
72+
0,
7373
"%n",
7474
"",
7575
}, {
@@ -82,7 +82,7 @@ func TestFrameFormat(t *testing.T) {
8282
"github.com/pkg/errors.init\n" +
8383
"\t.+/github.com/pkg/errors/stack_test.go:9",
8484
}, {
85-
Frame{},
85+
0,
8686
"%v",
8787
"unknown:0",
8888
}}
@@ -246,7 +246,7 @@ func caller() Frame {
246246
n := runtime.Callers(2, pcs[:])
247247
frames := runtime.CallersFrames(pcs[:n])
248248
frame, _ := frames.Next()
249-
return Frame(frame)
249+
return Frame(frame.PC)
250250
}
251251

252252
//go:noinline

0 commit comments

Comments
 (0)