Repository navigation
Conversation
scheduleFlush called b.wg.Add(1) from inside the goroutine it spawns instead of before starting it. Add must happen-before Wait observes the counter; calling it from within the goroutine means a concurrent Wait() can return while wg's internal counter is still zero and the flush hasn't even been registered yet, let alone run. In practice this lets Wait() return before the scheduled flush has actually flushed, which callers rely on it not doing. Move wg.Add(1) to the caller side of the goroutine so the registration happens-before any Wait() call can observe it. Also fixes a separate, pre-existing data race in the existing TestBucket test: it read TestFlusher.NumFlushes/FlushedEvents and bucket.bucket without synchronization while the flush goroutine concurrently writes them. Added a mutex to TestFlusher and locked reads. Adds TestBucketWaitBlocksUntilFlush, a deterministic test proving the happens-before ordering: fails consistently on the original code (Wait() returns with 0 flushes observed) and passes on the fix. Signed-off-by: samyfodil <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
scheduleFlushcallsb.wg.Add(1)from inside the goroutine it spawns, instead of before starting it:sync.WaitGroup's contract requiresAddto happen-beforeWaitobserves the counter. SinceAdd(1)here runs from inside the new goroutine, there's a window where the goroutine hasn't been scheduled yet, the counter is still 0, and a concurrent call toWait()returns immediately — before the flush has even been registered, let alone run.Fix
Move
wg.Add(1)to the caller side, beforego func() { ... }().Tests
Added
TestBucketWaitBlocksUntilFlush, which fails consistently on the original code (Wait()returns having observed 0 flushes) and passes on the fix. Verified: fails 10/10 with-race -count=10against the originalbucket.go, passes 20/20 against the fix.Also fixed a separate, pre-existing race in the existing
TestBucket: it readTestFlusher.NumFlushes/FlushedEventsandbucket.bucketwithout synchronization while the flush goroutine concurrently wrote them. Added a mutex toTestFlusherand locked the reads. Unrelated to thewg.Addbug itself, just something-racesurfaced while working in this file.go build ./...,go vet ./..., andgo test -race ./...are all clean on this branch.Related to #176, which is a separate, deeper race in
AdapterBase.Stop()found in the same file — this PR doesn't touch or fix that one.