fix(upstream): add WaitGroup to track background goroutines during shutdown #130
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
After PR #129, tests were still failing with
panic: Log in goroutine after test completedon macOS. Thectx.Err()checks added in PR #129 prevented the race between checking context state and logging, but goroutines could still be running when tests completed because there was no synchronization mechanism to wait for them.Root Cause
The
Managerstruct had:shutdownCtxandshutdownCancelfor signaling shutdownsync.WaitGroupto track background goroutinesWhen
ShutdownAll()orDisconnectAll()was called:testing.Tas doneEven with
ctx.Err()checks, there's a race window between the check and the log statement. The proper fix is to wait for goroutines to actually exit.Solution
Added proper goroutine lifecycle management with
sync.WaitGroup:1. Manager.shutdownWg Field
2. Track Goroutine Launches
In
NewManager():Dynamic restart:
3. Track Goroutine Exits
4. Wait During Shutdown
ShutdownAll()- with timeout:DisconnectAll()- blocking wait:Testing
Local Testing (5 consecutive runs with race detector)
$ go test ./internal/runtime -run TestUpdateListenAddressValidation -v -race -count=5 === RUN TestUpdateListenAddressValidation logger.go:146: 2025-11-04T10:10:51.450+0200 INFO Shutting down all upstream servers logger.go:146: 2025-11-04T10:10:51.450+0200 INFO OAuth event monitor stopped due to context cancellation logger.go:146: 2025-11-04T10:10:51.451+0200 INFO All background goroutines exited cleanly --- PASS: TestUpdateListenAddressValidation (0.30s) ... PASS (5/5 runs)Comprehensive Test Suite
$ go test ./internal/upstream ./internal/runtime -v -race -count=2 PASS (all tests passed)Changes Summary
shutdownWg sync.WaitGroupfieldshutdownWg.Add(1)before goroutine launches (2 locations)shutdownWg.Add(1)before restarting recovery monitordefer shutdownWg.Done()at function startdefer shutdownWg.Done()at function startRelated Issues
ctx.Err()checks added in PR fix(upstream): use ctx.Err() instead of select-default for context checks #129panic: Log in goroutine after TestUpdateListenAddressValidation has completedWhy This Fix Works
The previous fixes (PR #122-#129) focused on preventing logging after context cancellation. This fix ensures goroutines actually finish before tests complete. The WaitGroup provides synchronization that:
Add(1))defer Done())Wait())This is the correct and idiomatic Go pattern for managing background goroutine lifecycles.
🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com