Skip to content

durable_manager.test: assert sem-implies-on-disk, not a timing race (#551) - #577

Merged
ohohoreilly merged 1 commit into
masterfrom
ohohoreilly/551-sem-implies-on-disk
Oct 2, 2026
Merged

ohohoreilly merged 1 commit into
masterfrom
ohohoreilly/551-sem-implies-on-disk

Conversation

@ohohoreilly

@ohohoreilly ohohoreilly commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Fixes the #551 flake for real. Test-only.

Why the first fix didn't hold

SemFiresOnlyAfterFlush asserted that the durability sem had not fired just after Save(), on the premise that the writer waits out its write delay before flushing. #553 guarded that assertion on elapsed time and widened the delay to 2s. It still failed on aarch64 on 09-15, 09-18 and 09-19, each time with the fix in place.

The premise is false. Util::SleepUntil has had its comparison inverted since 2014 and never sleeps (#576). So TFlush::WaitFor returns at once, and the writer flushes the moment a save arrives. The negative assertion was a race between the writer and the test thread's very next instruction. The 2s delay couldn't help, because it is never applied.

What changes

The fixture now checks the #277 property in the direction that cannot race. After sem.Pop(), the durable file must already be in the engine's file set:

  • TFileService::InsertFile adds the file to its map synchronously, before queueing the op.
  • TSortedByIdFile's constructor waits on that op's completion.
  • Only then does ReleaseSavers push the sem.

So the check holds on every interleaving and can't fail on correct code. A pre-#277 synchronous push still fails it, because Pop() returns while the file is still being written. That is proven below.

The write delay goes back to the 300ms the other fixtures use. It is a no-op either way until #576 is decided.

Proven to catch the regression

A throwaway branch reintroduced the pre-#277 behavior (signal_now = true in Save()), and ci.yml was dispatched on it. Result: make test failed on exactly the new assertion (run 36960134990; branch since deleted):

[orly/indy/disk/durable_manager.test.cc, 197](bool)!durable_files.empty(); !1; fail
end SemFiresOnlyAfterFlush; fail

…551)

SemFiresOnlyAfterFlush asserted that the durability sem had not fired
right after Save(), on the premise that the writer waits out its write
delay before flushing. It never has. Util::SleepUntil's comparison is
inverted, so it never sleeps (#576), and the writer flushes the moment a
save arrives. The negative assertion was a race between the writer and
the test thread's next instruction, which aarch64 lost three times after
#551's fix. Widening the delay to 2s could not help, because the delay is
never applied.

Check the #277 property in the direction that cannot race instead: after
sem.Pop(), the durable file must already be in the engine's file set. The
writer inserts it (InsertFile adds it to the map synchronously) and waits
for that op before ReleaseSavers pushes the sem, so this holds on every
interleaving. A pre-#277 synchronous push still fails it, because Pop()
returns while the file is still being written.
@ohohoreilly ohohoreilly self-assigned this Oct 2, 2026
@ohohoreilly
ohohoreilly merged commit 69f3935 into master Oct 2, 2026
10 checks passed
@ohohoreilly
ohohoreilly deleted the ohohoreilly/551-sem-implies-on-disk branch October 2, 2026 11:02
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