Repository navigation
fix: wait for fleet server goroutines before test teardown to eliminate data race - #7714
Conversation
|
This pull request does not have a backport label. Could you fix it @ycombinator? 🙏
|
There was a problem hiding this comment.
Pull request overview
This PR addresses an intermittent -race failure in internal/pkg/server integration tests by ensuring Fleet Server goroutines fully exit before testing.T teardown, preventing late logs via zerolog.TestWriter from racing with test cleanup.
Changes:
- Derives a dedicated cancellable server context for the Fleet Server run loop in
startTestServer. - Registers a
t.Cleanupto cancel the server context and wait for the server goroutine group to exit. - Uses the derived server context when waiting for server readiness.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
TL;DRThe Buildkite failure is a test failure in Remediation
Investigation detailsRoot Cause
This check is in The failing Buildkite run reports only this test failing while all other E2E tests pass, which is consistent with a test-specific assertion race/fragility rather than a broad service outage. Evidence
Code evidence:
Verification
Follow-upIf this test still flakes after loosening log matching, consider recording/checking the UNENROLL action via a structured API-level signal instead of stderr text parsing. What is this? | From workflow: PR Buildkite Detective Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not. |
…a race When startTestServer ran srv.Run in an errgroup goroutine, no code guaranteed that goroutine had exited before testing.T was torn down. The loggedRunFunc in fleet.go logs when a subsystem exits; if that log fires after the test ends, the zerolog TestWriter races with the test framework's cleanup of testing.T, triggering the race detector. Fix: derive a srvCtx with cancel from the caller-supplied context, and register a t.Cleanup that cancels srvCtx then waits on the errgroup. By the time testing.T is invalidated, all fleet server goroutines have already stopped. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ad73fbd to
abe9ecc
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The change is small, targeted to test lifecycle management, and directly addresses the reported race by ensuring server goroutines exit before testing.T teardown.
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Lite
When startTestServer fails during waitServerUp, the cleanup's waitExit() call could surface a secondary error that was a consequence of the same startup failure, creating confusing duplicate test failures. Gate the t.Errorf call on serverUp so goroutine cleanup always runs (preventing leaks) but exit errors are only reported after the server is confirmed healthy. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
🟢 Approval recommended
The change is narrowly scoped to test infrastructure and correctly ensures server goroutines are stopped before testing.T teardown, addressing the described data race.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
internal/pkg/server/fleet_integration_test.go:237
srvCtxis shadowed by theerrgroup.WithContextassignment, which makes it easy to confuse the pre-errgroup cancelable context with the errgroup-derived context. Avoid the shadowing to keep the shutdown wiring obvious.
- Files reviewed: 1/1 changed files
- Comments generated: 0 new
- Review effort level: Lite
|
Tick the box to add this pull request to the merge queue (same as
|
|
@Mergifyio backport 9.5 9.4 8.19 |
✅ Backports have been createdDetails
No pull request needed: No commits between 9.5 and mergify/bp/9.5/pr-7714
No pull request needed: No commits between 9.4 and mergify/bp/9.4/pr-7714
No pull request needed: No commits between 8.19 and mergify/bp/8.19/pr-7714 |
What is the problem this PR solves?
The integration tests in
internal/pkg/serverintermittently fail the race detector with:loggedRunFunc(called by subsystem goroutines insiderunSubsystems) logs when each subsystem exits using the zerolog context logger. In tests, that logger has azerolog.TestWriterthat writes totesting.T.Logf. If a subsystem goroutine logs its exit message after the test'stesting.Thas been torn down, the race detector fires.How does this PR solve the problem?
startTestServerwas startingsrv.Runin an errgroup goroutine but never guaranteed that goroutine had fully exited beforetesting.Twas invalidated.The fix: derive
srvCtxwith its own cancel from the caller-supplied context, and register at.Cleanupthat:srvCancel()to signal the fleet server to stop.tsrv.waitExit()to block until all goroutines have exited, failing the test if the server exits with an unexpected error.By the time
testing.Tis cleaned up, every fleet server goroutine — includingloggedRunFunc— has already returned.Related issues