fix(processtree): stop the exit manager racing on its stop channel (SUB-7847)
The cleanup loop read pt.exitCleanupStopChan in its select on every iteration while stopExitManager wrote nil to the same field, neither side synchronised. Every one of the seven data races the race detector reports in pkg/processtree is this one field pair — exit_manager.go:41 write against :67 read — and it failed five tests in the creator package. Two further defects fell out of the same code, both reproduced rather than inferred: - Two concurrent Stop() calls could both pass the nil check and both reach the select's default branch, so both closed the channel: "panic: close of closed channel". - A loop that read the nilled field rather than the closed one blocked forever on a nil-channel receive, killing that select arm, so the loop kept ticking and mutating the tree for the lifetime of the process. Which of the two happened was decided by the race itself. The loop now takes the channel as an argument and never reads the field, and both lifecycle transitions are held under a dedicated mutex. close() is still the stop signal and nil is still the restartable "not running" flag, so the observable contract does not move: TestStartStop and TestExitManager_StartStop pass with their nil-after-stop assertions untouched. A dedicated mutex rather than pt.mutex, because the tree lock is held across performExitCleanup and reusing it would couple shutdown to tree contention. Documents the lifecycle in docs/features/process-tree-exit-manager- lifecycle.md, including one property worth knowing before writing tests here: closing the channel does not preempt an in-flight iteration, and when both select arms are ready the runtime chooses at random, so a cleanup pass can still run after Stop() returns. The guarantee is prompt termination, not zero further work. Verified in the Linux container, since macOS cannot build this package: go vet ./pkg/processtree/... && go test -race ./pkg/processtree/... vet clean, 0 race reports, every package ok — down from 7 races and 5 failing tests on the same command at 8866b6c8. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Alon <alon@armosec.io>
A
Alon committed
21a4fed6f21df3b74d052a8a3cd7b17e86743198
Parent: 8866b6c