Commit c7894924 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

runtime/pprof: handle empty stack traces in Profile.Add

If the caller passes a large number to Profile.Add,
the list of pcs is empty, which results in junk
(a nil pc) being recorded. Check for that explicitly,
and replace such stack traces with a lostProfileEvent.

Fixes #18836.

Change-Id: I99c96aa67dd5525cd239ea96452e6e8fcb25ce02
Reviewed-on: https://go-review.googlesource.com/36891Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent eae657e9
......@@ -267,13 +267,18 @@ func (p *Profile) Add(value interface{}, skip int) {
stk := make([]uintptr, 32)
n := runtime.Callers(skip+1, stk[:])
stk = stk[:n]
if len(stk) == 0 {
// The value for skip is too large, and there's no stack trace to record.
stk = []uintptr{funcPC(lostProfileEvent)}
}
p.mu.Lock()
defer p.mu.Unlock()
if p.m[value] != nil {
panic("pprof: Profile.Add of duplicate value")
}
p.m[value] = stk[:n]
p.m[value] = stk
}
// Remove removes the execution stack associated with value from the profile.
......
......@@ -635,3 +635,22 @@ func containsCounts(prof *profile.Profile, counts []int64) bool {
}
return true
}
// Issue 18836.
func TestEmptyCallStack(t *testing.T) {
t.Parallel()
var buf bytes.Buffer
p := NewProfile("test18836")
p.Add("foo", 47674)
p.WriteTo(&buf, 1)
p.Remove("foo")
got := buf.String()
prefix := "test18836 profile: total 1\n"
if !strings.HasPrefix(got, prefix) {
t.Fatalf("got:\n\t%q\nwant prefix:\n\t%q\n", got, prefix)
}
lostevent := "lostProfileEvent"
if !strings.Contains(got, lostevent) {
t.Fatalf("got:\n\t%q\ndoes not contain:\n\t%q\n", got, lostevent)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment