Skip to content

manifest lock tests: 100ms TTL fixtures fail under machine load, interchangeably #51

Description

@iceteaSA

Third sighting, now costing real time on unrelated PRs. Filing rather than widening #50.

What happens

manifest_lock_aba_regression members fail under full-gate parallelism and pass in isolation. Different members on different runs:

run 1   opencode_files.rs:1449   old_quarantine_name_with_recent_mtime_is_retained
                                 assertion failed: quarantine.exists()
run 2   opencode_files.rs:1334   malformed_diagnostic_owner_fields_are_tolerated_and_evictable_once_stale
run 3   pass

Isolated, the module is 13/13 and the whole ck-auth bin is 39/39, repeatedly.

Why

The fixtures use a 100ms TTL:

reclaim_options(Duration::from_millis(100))

The test body's own wall-clock duration is not bounded relative to that window, so on a busy machine the fixture crosses its own TTL before the assertion runs. Which member trips is a function of scheduling, not of the member — hence the interchangeability.

What this is not

I nearly filed this as a branch regression. I measured master passing a full gate while my branch failed twice, and had a plausible mechanism ready (a new async test adding parallel work, lengthening wall time inside those windows). Run 3 on my branch passed, which kills it — and the loads were not comparable anyway, because I was generating them myself with back-to-back gate runs: master ran at 2.4, mine at 3.9.

So: not branch-caused, and I have no clean measurement of whether added parallel work makes it more likely, because I contaminated the conditions.

The shape of the fix, from the one that already worked

#33 fixed a sibling member (owner_that_becomes_stale_during_retry_window_is_evicted) by converting the race into arithmetic: make the work inside the lock outlast the TTL by construction (sleep(ttl + 50ms)), so the outcome no longer depends on how fast the machine happens to be. That test then passed 10/10 at idle and failed 10/10 with the defect reverted — a real oracle in both directions.

The surviving members want the same treatment: either bound the elapsed time explicitly, or inject the clock so the fixture's notion of "now" is not the machine's.

The cheap-looking alternative — raising the TTL — only moves the load threshold at which it fails. That is what makes this class persistent: every individual failure looks like a flake worth re-running, and a green re-run at low load looks like a fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions