Skip to content

Make worker-convergence TAP cases deterministic - #105

Open
matt-welch wants to merge 1 commit into
mainfrom
fix/ci-pr103-flakes
Open

matt-welch wants to merge 1 commit into
mainfrom
fix/ci-pr103-flakes

Conversation

@matt-welch

Copy link
Copy Markdown
Contributor

Description

Two cases in test/t/23_fiction_worker_convergence.pl assert on short windows by polling, and both fail intermittently in CI on main since the search-slot change in #103. Case 3 is the TAP failure currently showing up on open PRs. This PR makes both cases deterministic by holding the system at the moment each one checks, using two new injection points. What each case asserts is unchanged.

  • Case 3 checks that a database that isn't live yet is granted 0 search threads and parks 0 slots.
    • The 0 grant lasts only from the reconcile that spawns the worker until the worker's own launcher kick, a few milliseconds. On a loaded runner the poll loop usually saw only the stale grant left on the paused row, then the final grant of 5.
    • The new injection point vamana-worker-before-publish-pid in VamanaWorkerServe holds the spawned worker just before it publishes its pid. The case then reads the grant and the worker's search_slots_registered.
    • The slot check uses search_slots_registered instead of counting search slots in pg_stat_activity. A slot parked before the worker publishes its pid fails its first owner check and exits right away, so the activity count reads 0 whether or not a slot was parked.
  • Case 13 checks that a crashed worker's search slots outlive it when its release-on-exit callback fails, then exit on their own.
    • The launcher's dead-entry cleanup clears workerPid. After that, an orphan can reach its next owner poll and exit before the test samples the survivors.
    • The new injection point vamana-launcher-before-reconcile in the launcher loop holds the launcher across the crash. The crash points are detached before the launcher is released, so the respawned worker doesn't trip them a second time.
  • INJECTION_POINT compiles to nothing on builds without injection points. On those builds the two case 3 assertions are skipped, as cases 12 and 13 already are.

No product behavior changes.

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Refactor / code cleanup
  • Documentation update
  • Test addition or update
  • Build / CI change

Pre-Merge Checklist

Build

  • make completes without errors or warnings
  • make install completes successfully

Tests

  • If this PR introduces no new behavior: existing regression tests (make installcheck) and TAP tests (test/t/) pass with no failures
  • If this PR introduces new behavior: test cases covering it were added to test/sql/ and/or test/t/
  • If this PR adds a standalone unit-test module under test/modules/: it builds and passes (make -C test/modules/<module> installcheck)

Documentation

  • Relevant docs under docs/ updated if architecture or usage changed

Testing Notes

All runs were on this branch, which is based on current main, with injection points enabled.

  • Build: make WERROR=1 and make install are clean, with no warnings.

  • Full suites:

    • Full TAP suite: 72 files, 1529 tests, all pass.
    • SQL regression with ci/test_server.conf: 10/10.
    • Hardware tests: prove_installcheck-hw passes (2 files, 55 tests), and installcheck-hw with ci/test_server.conf passes 2/2.
  • Flake rate: I ran 23_fiction_worker_convergence.pl 25 times under CPU contention: pinned to two CPUs with taskset, plus a busy loop on each CPU.

    Tree Failing runs
    main before Skip search slots until a database has an index #103 2/25 (case 13)
    current main, without this change 21/25
    this change 0/25
  • The new assertions can still fail: each was checked against an injected regression.

    • Clamping the worker's slot count to at least 1 fails the case 3 slot assertion.
    • Granting threads to a database that isn't live fails the case 3 grant assertion.
    • Running release-on-exit before the crash point fails the case 13 survivor assertion.

Other intermittent failures seen on main recently (58_residency_rollback_reconcile.pl, 73_primary_slot_catchup_scale.pl, and one vamana_databases SQL failure) are not addressed here. 58 and 73 predate #103.

Two cases in 23_fiction_worker_convergence.pl sampled windows that
nothing held open. On a loaded two-CPU machine case 3 failed in most
runs and case 13 in some.

 - Case 3 polled for the zero grant a not-yet-live database gets. That
   grant lasts only until the new worker's own launcher kick, a few
   milliseconds, so the poller usually saw the stale grant left on the
   paused row or the final one. A new injection point holds the spawned
   worker just before it publishes its pid, and the case asserts that the
   published grant and the worker's registered slot count are both 0
   while it is held.
 - The case 3 slot check reads search_slots_registered instead of
   counting search slots in pg_stat_activity. A slot parked before the
   worker publishes its pid fails its first owner check and exits at
   once, so the activity count reads 0 whether or not a slot was
   parked.
 - Case 13 sampled a crashed worker's orphaned search slots before
   their next owner poll, which can come at any point within 2 s of the
   launcher clearing the dead entry. A new injection point holds the
   launcher across the crash, so the orphans survive until the test
   releases it. The crash points are detached before the release, so
   the respawned worker no longer trips them a second time.

Signed-off-by: Matt Welch <matt.welch@intel.com>
@matt-welch
matt-welch requested a review from a team October 28, 2026 18:35
@matt-welch matt-welch added the CI Related to continuous integration (CI) testing. label Oct 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI Related to continuous integration (CI) testing.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant