Skip to content

sleep, syncevent: park with a sync wait reason - #16782

Open
adios-404 wants to merge 1 commit into
google:masterfrom
adios-404:sleep-park-goroutineleak
Open

adios-404 wants to merge 1 commit into
google:masterfrom
adios-404:sleep-park-goroutineleak

Conversation

@adios-404

Copy link
Copy Markdown

Fixes #15412.

Since Go 1.27 (gVisor builds with 1.27.3), the goroutineleak profile is always available. Sleeper.nextWaker and syncevent.Waiter park with WaitReasonSelect but have no channel sudogs, so collecting the profile marks them as leaked, and the next goready throws "bad g->status in ready". Idle netstack TCP processors park in Sleeper.Fetch, so one GET of /debug/pprof/goroutineleak served through a gonet listener kills the process.

This parks the three sites with WaitReasonSemacquire/TraceBlockSync, as sync.Gate already does; the leak detector never treats those waits as leak candidates. Apart from the new tests, the diff only changes the reasons passed to gopark, drops two unused constants and updates comments. Stack dumps now show these waits as semacquire, which the Sentry watchdog's stuck-goroutine filter also matches.

The fix is @Asutorufa's change from #15366. This PR adds regression tests for Sleeper.Fetch, Waiter.WaitFor and Waiter.WaitAndAckAll; on master they fail without killing the test binary. Asutorufa, thanks for the report and the fix; if you would rather send your own PR, I'm happy to close this one.

The new tests fail on master and pass with this change (40 of 40 runs each, Go 1.27.3). go test of pkg/sleep, pkg/syncevent (also with -race) and the netstack TCP packages passes on macOS. With Bazel on Linux, //pkg/sleep/..., //pkg/syncevent/..., //pkg/sync/... and //pkg/tcpip/transport/tcp/... pass (nogo included), as does //:gazelle_check; goimports, buildifier and codespell are clean on the changed files.

Sleeper.nextWaker, Waiter.WaitFor and Waiter.WaitAndAckAll park with
WaitReasonSelect, but they have no channel sudogs. Since Go 1.27 the
goroutineleak profile is always available. When it is collected, the
GC marks such a goroutine as leaked, and the next goready throws "bad
g->status in ready". In netstack, idle TCP processor goroutines park in
Sleeper.Fetch, so one GET of /debug/pprof/goroutineleak served through
a gonet listener kills the process.

Park with WaitReasonSemacquire and TraceBlockSync, as sync.Gate does.
The leak detector never treats such waits as leak candidates. The
park/wake protocol does not change.

Asutorufa first proposed this change in google#15366.

Fixes google#15412
@github-actions
github-actions Bot requested review from kerumeto and trantoji October 31, 2026 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pkg/sleep: goroutineleak profiling causes "bad g->status in ready" on wake-up (Go 1.27)

1 participant