Skip to content

Raise the Ubuntu test step timeout above its measured runtime - #13

Merged
FuryBaM merged 2 commits into
agent/stabilize-foundationfrom
claude/local-language-benchmarks-9en3eo
Aug 8, 2026
Merged

Raise the Ubuntu test step timeout above its measured runtime#13
FuryBaM merged 2 commits into
agent/stabilize-foundationfrom
claude/local-language-benchmarks-9en3eo

Conversation

@FuryBaM

@FuryBaM FuryBaM commented Aug 8, 2026

Copy link
Copy Markdown
Owner

build-and-test (ubuntu-24.04, Debug) failed on b286d07 without a single test failing. It was killed at the 20-minute step limit:

464/474 Test #464: absolute.run-ownership-stability ..... Passed  0.00 sec
        Start 465: absolute.emit-simd-vectorization
##[error]The action 'Test (Ubuntu)' has timed out after 20 minutes.
...
Terminate orphan process: pid (3986) (ctest)
Terminate orphan process: pid (5816) (absolutec)

Why this is timing, not a defect

The same commit passed in the parallel run of the same workflow:

Run Duration Result
31265401859 22m53s killed at the 20-minute step cap
31265403716 14m13s passed

Identical input, two runners, a 1.6x spread. The Debug suite sits close enough to the cap that ordinary runner variance decides the outcome. Release is unaffected — it finishes in roughly 5 minutes. 464 of 474 tests had already passed when the step was killed, so nothing was stuck; the budget simply ran out.

The change

Test (Ubuntu) goes from 20 to 35 minutes, and the job from 45 to 60 so the step ceiling rather than the job ceiling is what a genuine hang hits.

This does not weaken the failure detection that matters. ctest keeps its own --timeout 180, so a single wedged test is still caught in three minutes regardless of the step budget. What the step limit catches is a whole-suite deadlock, and that is exactly the case where waiting longer costs nothing but a few idle runner minutes.

What would be better

Cutting the runtime rather than raising the ceiling. ctest runs serially here while the build steps already use --parallel 2, so there is real headroom. That is a larger change than it looks: some tests bind ports and write shared paths, so each needs checking for isolation before parallelising, and getting it wrong trades a predictable timeout for unpredictable flakes. Left for a separate change rather than folded in here.

Verification

The workflow parses and the values land where intended:

job timeout-minutes: 60
  build_linux  -> 25
  build_windows -> 25
  test_linux   -> 35
  test_windows -> 20

Whether the timeout is actually gone can only be shown by CI over several runs, since the failure is intermittent by nature.


Generated by Claude Code

build-and-test (ubuntu-24.04, Debug) failed on b286d07 without any test
failing. It was killed at the 20-minute step limit with 464 of 474 tests
already passed, mid-way into starting the 465th, and the orphaned ctest,
tee and absolutec processes were reaped by the runner.

The same commit passed in the parallel run of the same workflow, where the
job took 14m13s against the 22m53s of the one that timed out. That 1.6x
spread across two runners on identical input is the whole story: the Debug
suite sits close enough to the cap that ordinary runner variance decides
the outcome. Release is unaffected because it runs far quicker.

Raise the Ubuntu test step to 35 minutes and the job to 60 so the step
ceiling, not the job ceiling, is what a genuine hang hits. The step still
fails fast on a real deadlock, and ctest keeps its own 180-second per-test
timeout, so a single wedged test is still caught in seconds rather than
after the step budget.

This trades a longer worst case for not failing on healthy runs. Cutting
the runtime itself, by giving ctest a --parallel, is the better fix but a
larger change: the suite runs serially today and some tests bind ports and
write shared paths, so parallelising needs each test checked for isolation
first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SPqntJmyXNSmZNzuQWj5QS

FuryBaM commented Aug 8, 2026

Copy link
Copy Markdown
Owner Author

language-stress-and-fuzz failed on 8f60a85. It is not caused by this PR, and the mechanism rules it out rather than the statistics:

  • this PR's entire diff is two timeout-minutes values inside the build-and-test job of .github/workflows/ci.yml
  • language-stress-and-fuzz is defined in .github/workflows/test-hardening.yml, a different workflow

A step timeout in one workflow's job cannot affect a job in another. The sibling run's copy of this job is still queued, so the usual one-failed-one-passed confirmation is not available yet, but it is not needed for the causal question.

This job is the known intermittent Linux failure documented on #12: it has previously failed and passed on the same commit across parallel runs, and the stress binary passes 300 consecutive local runs. It is pre-existing and tracked separately from this change.

The signal this PR actually needs is build-and-test (ubuntu-24.04, Debug) completing instead of being killed at the step cap. Both copies are still running. Note that macos-smoke will also fail here, with its single run-sanitizer-ownership-stability test — also pre-existing, and it means the required gate on this PR cannot go green regardless of whether the timeout fix works.


Generated by Claude Code

The backend selected a target CPU with getHostCPUName() and passed an empty
feature string, so LLVM enabled every feature implied by that microarchitecture.
The name only identifies a model; it says nothing about which instructions the
machine actually exposes. A virtualised host can report a model whose default
feature set includes instructions the hypervisor masks off, and generating for
the name alone then emits code the CPU refuses to run, which surfaces as SIGILL
in whatever executes the generated binary.

Take the feature string from getHostCPUFeatures() instead. The signature changed
in LLVM 19 from an out-parameter to a returned map, so the call is guarded the
same way Host.h already is, and SubtargetFeature.h joins it in the PCH under the
existing version guard.

What prompted this: build-and-test (ubuntu-24.04, Debug) failed on 8f60a85 with
nine tests, eight of them ILLEGAL, and both parallel runs produced an identical
list. The same source passed all 474 tests an hour earlier in job 93122612240,
so the source is not what changed. The failures cluster on tests that execute
generated native code, which is the signature this defect produces.

Also log lscpu on Linux, so the next run records the runner's model and feature
bits instead of leaving them to be inferred from a signal number.

Verification is honest about its limits: this cannot be reproduced locally,
because getHostCPUName() here reports cascadelake on a machine that genuinely
has AVX-512, so name and features agree and no illegal instruction is possible.
The local Debug run confirms the change causes no regression; confirming it
fixes the CI failure needs a hosted run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SPqntJmyXNSmZNzuQWj5QS

FuryBaM commented Aug 8, 2026

Copy link
Copy Markdown
Owner Author

Both changes on this branch are now confirmed by CI, and the second one turned out to matter far more than the first.

The timeout raise did its job

On 8f60a85 the Ubuntu Debug suite ran to completion in 1216s and 1249s — 20.3 and 20.8 minutes — instead of being killed at the old 20-minute cap. The suite genuinely did not fit, by a margin small enough that runner speed decided the outcome.

What completing the run exposed

With the step no longer killed, both parallel runners failed with an identical 9-test list, 8 of them ILLEGAL:

192 run-math-plugin              333 run-std-priority-queue     389 run-std-encoding
194 run-math-plugin-integration  335 run-std-hash-collections   436 run-task-scheduling
288 abi-linker-corpus-native     377 run-generic-callback-abi   468 run-simd-vectorization

Identical results on two independent runners is deterministic, not flaky — so the earlier "intermittent Linux failure" framing was wrong. The same source had passed all 474 tests an hour before (job 93122612240, 14m13s), so the code was not what changed.

Root cause

Absolute-CodeGen/src/codegen_module.cpp selected a target CPU from getHostCPUName() but passed an empty feature string. Those are different things: the name identifies a microarchitecture from CPUID family/model, and LLVM then enables every feature that microarchitecture implies. A virtualised host can report a model whose default feature set includes instructions the hypervisor masks off — so the backend emits, say, AVX-512, and the CPU rejects it. ILLEGAL is literally SIGILL.

That explains every symptom: the signal itself, tests spanning plugins, ABI, encoding, SIMD and scheduling (all of which execute generated native code), no local reproduction, and the switch from green to red without a code change.

The fix takes the feature string from getHostCPUFeatures(), guarded for the signature change between LLVM 18 (bool f(StringMap&)) and 19+ (returns by value).

Result on 65df49c

Job 8f60a85 65df49c
build-and-test (ubuntu-24.04, Debug) 9 failures, both runners success, 19m51s
language-stress-and-fuzz failure success, both runs
ubuntu Release, both Windows, llvm-compatibility 18/19/20/21, termux, wasm, TSan green green
Hardening required gate failure success, both runs

language-stress-and-fuzz going green in both runs fits the same cause — it also executes generated code.

Two caveats stated plainly: the second Debug job is still running, and because the trigger was environmental I cannot fully exclude that the runner fleet simply rotated back. The mechanism is sound and the fix is correct regardless, but a few more runs are what would settle it. The lscpu line added to the Linux toolchain log will make the next occurrence diagnosable from the artifact instead of by inference.

macos-smoke still fails with its single pre-existing run-sanitizer-ownership-stability test — unchanged in count, which also confirms the codegen change did not affect macOS/arm64. The required gate here cannot go green while it fails.


Generated by Claude Code

@FuryBaM
FuryBaM merged commit ef6f8ef into agent/stabilize-foundation Aug 8, 2026
28 of 32 checks passed
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