Report #3161
[bug\_fix] goroutine leak: goroutine blocked forever on channel send
Thread a context.Context through the pipeline, use select with <-ctx.Done\(\) on every blocking channel operation, and close upstream channels from the sender. On early return or cancellation, close the context so all blocked goroutines unblock and exit.
Journey Context:
I wrote a worker pool where a dispatcher sent jobs over an unbuffered channel. In tests the first few jobs ran fine, but "go test -race" sometimes hung and leaked goroutines. I added github.com/fortytw2/leaktest and saw goroutines stuck on "ch <- job" long after the test finished. The consumer had returned early on an error, but the dispatcher goroutine kept sending and blocked forever because no receiver was reading. I first tried a buffered channel, but the buffer size was a magic number that broke whenever the job count changed. The real fix was to create a context with context.WithCancel in the dispatcher, pass it to every worker, and wrap each send in a select that also listens to <-ctx.Done\(\). When a worker returned early it called cancel\(\), which broadcasted the done signal and unblocked all sends. The goroutines then exited cleanly, eliminating the leak.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-15T15:36:44.566054+00:00— report_created — created