Skip to content

fix(mvcc): deterministic GC Dispose (fixes flaky DisposeStopsBackgroundCollectionTest on main)#5

Merged
dmitrat merged 1 commit into
mainfrom
fix/mvcc-gc-dispose-race
Jun 13, 2026
Merged

fix(mvcc): deterministic GC Dispose (fixes flaky DisposeStopsBackgroundCollectionTest on main)#5
dmitrat merged 1 commit into
mainfrom
fix/mvcc-gc-dispose-race

Conversation

@dmitrat

@dmitrat dmitrat commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Problem

main went red after #4 merged: MvccGarbageCollectorTests.DisposeStopsBackgroundCollectionTest failed with Expected: 5, But was: 6. It passed on the #4 PR run and failed on the post-merge main run on the same code — a timing-dependent flake, not introduced by #4.

Root cause

MvccGarbageCollector.Dispose() called Timer.Dispose(), which does not wait for an already-running timer callback. A collection cycle that started just before Dispose() could complete and increment RunCount after Dispose() returned, so the test's "no runs after Dispose" invariant only held when timing cooperated. Pre-existing race in a subsystem untouched by #4 — the noisy main runner just surfaced it.

Fix

Use the Timer.Dispose(WaitHandle) overload and wait on the handle — it signals once all callbacks have drained, guaranteeing no background collection runs after Dispose() returns and RunCount is final. (Same shutdown-correctness shape as the LsmParallelWriter fix in #4.)

Verification

MvccGarbageCollectorTests 14/14, stable across repeated local runs (was intermittently 5-vs-6).

🤖 Generated with Claude Code

…stic stop)

DisposeStopsBackgroundCollectionTest flaked on main after #4 (Expected 5, was 6):
MvccGarbageCollector.Dispose() called Timer.Dispose(), which does NOT wait for an
already-running callback. A collection cycle that started just before Dispose could
finish and bump RunCount afterwards, so 'no runs after Dispose' held only when the
timing happened to cooperate (green on the PR runner, red on main).

Use the Timer.Dispose(WaitHandle) overload and wait for the handle: it signals once
all callbacks have drained, so no background collection runs after Dispose returns
and RunCount is final. Pre-existing race in a subsystem untouched by #4 - just
surfaced by runner timing. MVCC GC fixture 14/14, stable across repeated runs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dmitrat dmitrat merged commit 35c56bc into main Jun 13, 2026
1 check passed
@dmitrat dmitrat deleted the fix/mvcc-gc-dispose-race branch June 13, 2026 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant