Ownership and lifecycle
processownership
Checks that started os/exec commands are waited on or transferred to a wait owner.
What it detects
Tracks commands successfully started with os/exec and reports return paths
that neither wait for the process nor transfer the command to code that owns
waiting for it.
Checks
| Check | What it detects |
|---|---|
missing-wait |
Reports successfully started commands that are neither waited on nor transferred. |
Why this is flagged
Starting a process without waiting for it can leave operating-system resources unreleased and loses the process’s final error or exit status. Waiting gives the child process a complete, observable lifecycle.
Further reading: exec.Cmd.Wait.
How to fix it
Use Run when the program can wait immediately. If it must use Start, make
sure every successful start is followed by Wait, and handle the resulting
exit status or error.
Examples
Flagged code
func run(ctx context.Context) error { command := exec.CommandContext(ctx, "worker") // gohawk: started command is not waited on every successful return path return command.Start()}Accepted code
func runSafely(ctx context.Context) error { command := exec.CommandContext(ctx, "worker") if err := command.Start(); err != nil { return err } return command.Wait()}