Open nsrip-dd opened 2 weeks ago
Related Issues and Documentation
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Related Issues and Documentation
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
In triage, we don't think it's super important to show chanrecv1
here (the line in the user code should already point to the channel operation), but we understand the general concern about maintaining parity with older versions.
Go version
go version go1.23.1 darwin/arm64
Output of
go env
in your module/workspace:What did you do?
Built this program with PGO and ran it:
What did you see happen?
If I build with PGO using a profile where
runtime.blockevent
is hot, then I see this output:Example program which generates such a CPU profile:
```go package main import ( "os" "runtime" "runtime/pprof" "time" _ "unsafe" ) //go:linkname blockevent runtime.blockevent func blockevent(cycles int64, skip int) func main() { runtime.SetBlockProfileRate(1) pprof.StartCPUProfile(os.Stdout) defer pprof.StopCPUProfile() now := time.Now() for time.Since(now) < 5*time.Second { for i := 0; i < 100000; i++ { blockevent(1, 1) } } } ```What did you expect to see?
I expected to see
chanrecv1
in the root frame:I see that if I run the program with frame pointer unwinding disabled (
GODEBUG=tracefpunwindoff=1
) or if I run it with Go 1.22.The problem is that if
runtime.saveblockevent
is inlined intoruntime.blockevent
, thengetfp()
will return one ofruntime.saveblockevent
's callers frame pointers here, andruntime.fpTracebackPartialExpand
will start frame pointer unwinding from the wrong frame, making the skip values incorrect. Depending on how much inlining there is, we might see even more missing frames.