Skip to content

Flaky test: SemaphoreTest.TryAcquireForWithTimeout fails ~1 in 3 runs in isolation #753

Description

@drsnuggles8

Describe the bug
SemaphoreTest.TryAcquireForWithTimeout (SemaphoreTest.cpp:57) fails intermittently. Unlike #625 this is not order-dependent — it fails in isolation, roughly 1 run in 3, with nothing else in the process:

build\OloEngine\tests\Debug\OloEngine-Tests.exe --gtest_filter=SemaphoreTest.TryAcquireForWithTimeout
[  PASSED  ] 1 test.
[  PASSED  ] 1 test.
[  FAILED  ] SemaphoreTest.TryAcquireForWithTimeout (1 ms)

It surfaced during a full-suite run for #691 Phase 3 (heap-off configuration), where it appeared once and did not recur on the next run of the same binary.

Root cause (unknown — and the two candidates want different fixes)
This is a timing assertion around TryAcquireFor, so it is one of:

  1. A test-side timing assumption. The test asserts something about elapsed time against a timeout, and the tolerance is too tight for a loaded machine. This box runs three GitHub Actions runners for another repository alongside development, so scheduler jitter is routine and the fix is a wider tolerance (or asserting a lower bound only).
  2. A real imprecision in the primitive. TryAcquireFor may return early — or report the wrong outcome — under contention. That would be an engine bug in a threading primitive, not a test bug, and it would matter well beyond this test.

Worth resolving which before "fixing" it. Widening the tolerance is the obvious move and would make the symptom go away in either case — including case 2, where it would bury a genuine bug in a synchronisation primitive. Establish which one it is first.

To Reproduce

build\OloEngine\tests\Debug\OloEngine-Tests.exe --gtest_filter=SemaphoreTest.TryAcquireForWithTimeout

Repeat ~5 times. Observed 2 passes / 1 failure in three consecutive isolated runs. A loaded machine makes it likelier.

Expected behavior
A deterministic test, or one whose tolerance is explicitly justified against scheduler jitter. A suite that fails 1-in-3 on an unrelated axis trains everyone to ignore red — which is exactly how the #691 depth-contract bug survived several rounds of "the suite is green".

Suggested fix

  1. Instrument the failing assertion to print the measured elapsed time versus the expected bound, so a failure says how far off it was rather than just that it was off.
  2. From that, decide between (a) widening/one-siding the tolerance with a comment stating the jitter budget, or (b) fixing TryAcquireFor.
  3. If it stays timing-sensitive by nature, consider asserting only the direction that cannot be jitter (e.g. "did not return before the timeout") rather than a two-sided window.

Not caused by #691. Confirmed: the branch's diff touches no threading code, and the failure reproduces in isolation on a build of that branch as well as appearing in only one of several full-suite runs.

Score

capability: 1
craft: 1
stability: 3
decay: 1
effort: 1
confidence: 0.8
learning: 2
fun: 1
kano: table-stakes
blocked_by: []
blocks: []

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrobustnessProduction hardening / shipping robustness

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions