Help us shape the future of Go! Take the 2026 Go Developer Survey

sendcheck

command
v0.22.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 21, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Command sendcheck fails when a goroutine hands a result to another goroutine (a channel send or a close) and only afterwards runs a deferred call that is more than a signal: a decrement, a slot release, an unlock, a flag reset. The receiver can act on the result before that bookkeeping runs, and finds the goroutine's state still claimed. That pattern was a real bug three times in bide (a notification call counted in flight after it had answered, a trail slot held after the head was published, a recovery slot held while the user's error handler ran), and each one showed up as a flaky test, not as a failure at the cause.

It reads every .go file below the root, test files included, and looks at each goroutine: a function literal started with go, a function value bound to a name in the same function, or a declared function (every declaration of an ambiguous name is checked; one it cannot find is reported, not skipped). A goroutine hands a result over when it sends on a channel, closes one, or calls a function that is handed a channel and sends on it (followed through the call graph, by name); function literals nested in the goroutine count as part of it. It is flagged when it then has bookkeeping: a deferred call, or a statement after the send on the same path (a decrement, an unlock, a release, a slot given back, a flag cleared, an entry deleted). Deferred WaitGroup.Done, cancel functions, closing a channel and Stop are signals and do not count. A goroutine whose order is safe goes in the allowlist (.sendcheck-allow) as

path|enclosing function|every deferred call and bookkeeping statement flagged, joined by " ; " # why

so a new bookkeeping call in an allowlisted goroutine is a new finding, and an allowlist entry that matches no goroutine is an error, so the list cannot rot. What it cannot see: a result handed over by a callback or a method on a channel held in a field, and anything started by a function it cannot name.

Usage, from the repository root:

go run ./internal/tools/sendcheck [-root dir] [-allow file]

The exit status is 0 when clean, 1 on findings, and 2 when the check could not run.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL