Skip to content

Wait for the evidence, not for the clock - #636

Merged
lmoresi merged 2 commits into
developmentfrom
bugfix/hang-report-test-no-timing
Aug 24, 2026
Merged

Wait for the evidence, not for the clock#636
lmoresi merged 2 commits into
developmentfrom
bugfix/hang-report-test-no-timing

Conversation

@lmoresi

@lmoresi lmoresi commented Aug 23, 2026

Copy link
Copy Markdown
Member

The end-to-end hang-report test raced a fixed window against machine speed and failed CI twice. Both failures were true reports of a slower runner rather than defects: the waiting group came back short because a rank had not been scheduled enough to dump, then the file filled with importlib._bootstrap frames because four oversubscribed ranks took longer to import than the 1 s watchdog allowed. Each fix was a bigger number tuned to a workstation, which is not a machine any runner resembles.

Timing is now out of it. The script arms its own watchdog after import — a known point in the program rather than a moment in the schedule — and writes a marker. The test waits for those markers, then waits for the blocked ranks to have dumped twice, then kills. Import may take as long as it likes; the blocked ranks are blocked until killed, so the wait always completes. The caps are backstops set far above any plausible duration, so reaching one means something is wrong rather than slow.

Two consequences worth noting:

  • sorted(biggest_ranks) == [0, 2, 3] is a legitimate assertion again. Every blocked rank is waited for by construction instead of hoped for — the weaker "which rank is blamed" form was a concession to the race.
  • It runs in 8.6 s instead of 86, because it kills as soon as the evidence exists.

Arming from the script leaves UW_HANG_WATCHDOG uncovered, so a separate single-rank test covers that path — it is the documented entry point, and the reason arming happens at import is that a rank which diverges before reaching a watch() call reports nothing.

8 passed locally.

Underworld development team with AI support from Claude Code

The end-to-end hang-report test raced a fixed window against machine speed, and
failed on CI twice. Both failures were true reports of a slower runner rather
than defects: first the waiting group came back short because a rank had not
been scheduled enough to dump, then the file filled with `importlib._bootstrap`
frames because four oversubscribed ranks took longer to import than the 1 s
watchdog allowed. Each time the fix was a bigger number tuned to a workstation,
which is not a machine any CI runner resembles.

Timing is now out of the test. The script arms its own watchdog AFTER import --
a known point in the program rather than a moment in the schedule -- and writes
a marker. The test waits for those markers, then waits for the blocked ranks to
have dumped twice, then kills. Import may take as long as it likes. The blocked
ranks are blocked until killed, so the wait always completes; the caps are
backstops against a broken run, set far above any plausible duration so that
reaching one means something is wrong rather than slow.

Two things follow. `sorted(biggest_ranks) == [0, 2, 3]` is a legitimate
assertion again, because every blocked rank is now waited for by construction
instead of hoped for -- the weaker "which rank is blamed" form was a concession
to the race. And the test runs in 8.6 s instead of 86, because it kills as soon
as the evidence exists rather than sitting out a window.

Arming from the script leaves `UW_HANG_WATCHDOG` uncovered, so a separate
single-rank test covers it: that entry point is the documented one, and the
reason arming happens at import is that a rank which diverges before reaching a
`watch()` call reports nothing.

8 passed.

Underworld development team with AI support from Claude Code
Copilot AI lite review requested due to automatic review settings August 23, 2026 22:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

`_check_velocity_preconditioner` asked `self.snes` for its fieldsplit sub-KSPs.
On the rotated free-slip path that KSP is never set up -- that path builds its
own -- so PETSc printed a full error banner before the exception could be
caught, making a healthy solve look broken. Skipped by path now.

Suppressing it with `PETSc.Sys.pushErrorHandler('ignore')` was tried first: it
is global state and broke 23 unrelated tests.

29 passed.

Underworld development team with AI support from Claude Code
@lmoresi
lmoresi merged commit c5e3940 into development Aug 24, 2026
2 checks passed
@lmoresi
lmoresi deleted the bugfix/hang-report-test-no-timing branch August 24, 2026 04:25
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.

2 participants