cancellationownership
Checks context and signal-derived cancellation functions proved lost on a normal return path.
What it detects
Tracks cancel functions returned by context and signal helpers and reports any successful return path that neither calls the cancel function nor transfers it to the caller.
Canceling a parent context, or receiving from the child’s Done channel, can
stand in for the child’s own cancel on the paths it covers. Signal
registrations from signal.NotifyContext still need their stop function.
The full list of precision boundaries, with the fixtures that pin each one, is in the cancellationownership design notes.
Checks
| Check | Tier | Kind | What it detects |
|---|---|---|---|
release |
core | defect | Reports derived cancel functions proved lost on a feasible normal return path. |
Why this is flagged
A derived context can retain timers, memory, and references to its parent until it is canceled. Calling the cancel function promptly releases those resources and tells dependent work to stop.
Further reading: Package context.
How to fix it
Keep the cancel function returned when the context is created. Usually, call
defer cancel() immediately after checking that creation succeeded, or call it
explicitly at the point where the derived work is finished.
Examples
Flagged code
func work(parent context.Context) { // gohawk: cancel function from context.WithCancel is not called on every return path ctx, cancel := context.WithCancel(parent) _ = cancel doWork(ctx)}Accepted code
func workSafely(parent context.Context) { ctx, cancel := context.WithCancel(parent) defer cancel() doWork(ctx)}