-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
For performance reasons, the Go runtime increasingly uses framepointer unwinding. The execution tracer uses framepointer unwinding since Go 1.21. Block and mutex profiles use framepointer unwinding since 1.23.
Unfortunately, framepointer unwinding is easily corrupted by custom assembly that clobbers the framepointer. For example, #69629 and #74851 were due to assembly in a dependency clobbering the framepointer, leading to crashes when unwinding.
go vet -framepointer can catch some cases of framepointer clobbering, but it can't cover every case with static analysis, and more importantly, it is often not run on dependencies.
Discover of these problems is also often delayed because framepointer unwinding is used primarily in optional diagnostics, so users may not see crashes until they try to collect one of the diagnostics.
The runtime has global constant debugCheckBP (default false). When enabled, stack copying verifies that framepointers are reasonable, and crashes if not. This discovers problems more proactively.
I propose we convert this check from a constant to a GODEBUG option (GODEBUG=checkfp=1), and enable this option by default with language version 1.26.
Enabling by default will help discover bad code more proactively. On the other hand, it will trigger crashes in code that works fine provided none of the framepointer diagnostics are used. Limiting the behavior change to an explicit upgrade to 1.26 in go.mod is intended to strike a balance here.
If we do this, we should also enhance the check to include more context and instructions to help users identify the source of the issue. We could also consider running this check more often than just during stack copy. Every traceback could theoretically do it?
Metadata
Metadata
Assignees
Labels
Type
Projects
Status