Skip to content

FEA: Recreate the host-libm plot-label hangs on a host-libm reference stage - #32

Merged
thclark merged 4 commits into
mainfrom
host-libm-hangs
Oct 26, 2026
Merged

thclark merged 4 commits into
mainfrom
host-libm-hangs

Conversation

@thclark

@thclark thclark commented Oct 25, 2026 •

Copy link
Copy Markdown
Owner

Hypothesis

On 2026-10-23, a run with twins found that four known-issues cases did not hang, although their cases.toml descriptions say the reference hangs in XFOIL's plot label (known issues 4.17). The hypothesis was that those descriptions date from the host-libm reference, and that moving to CORE-MATH (c193b5b, 2026-10-15) took these ill-conditioned runs off the path that reaches a non-finite value.

The history supports the dating. git log -S shows that all four descriptions were written in 2dcba97 (2026-10-08), a week before c193b5b. Since then the build patches and the vendored XFOIL have not changed.

What was found

All runs were references only, on macOS 15.6.1 arm64. They used the same panels and xfoil.inp that cargo xtask fixtures writes, under the same 120 s-without-output watchdog. In every hang, the last VISCAL record has CD = Infinity: the point ran to its iteration limit, CD went non-finite, and the sequence-plot label then loops forever (4.17).

Case CORE-MATH Host libm
naca4412_n240_polar30_re1e6_iter200 no hang: 27–30° fail, the downward leg halts at −19° hangs at 30°, upward leg, VISCAL call 31, SETBL call 1032
naca4412_n240_polar30_re3e6_iter200 no hang: the sweep completes hangs at −24°, downward leg, call 56, SETBL 1827
naca16-212_n160_polar30_re1e6_m07_iter100 no hang: the sweep completes hangs at −19°, downward leg, call 51, SETBL 1205, with the panels yFoil generated before c193b5b (today's panels: −18°, call 50)
naca64a010_n160_polar30_re1e6_type2_iter100 no hang: 12–15° fail, the downward leg halts at −4° no hang with today's panels; hangs at 12°, upward leg (call 13, SETBL 464, 11 of 13 points converged, as described) with the panels yFoil generated before c193b5b

For contrast, the three cases that still hang on CORE-MATH:

Case CORE-MATH Host libm
naca0012_n240_polar30_re1e6_iter200 hangs at 24° (call 25, SETBL 766) hangs at 22°, which is what its description said
naca4412_n240_polar30_re1e6_m06_iter200 hangs at 21° (call 22, SETBL 585) not run
naca64a010_n160_polar30_re1e6_m03_type2_iter100 hangs at 13° (call 14, SETBL 736) not run

The hypothesis holds, with one refinement. c193b5b also moved yFoil's own geometry generators onto CORE-MATH, so the 16-212 and 64A010 panels changed: 4 and 116 lines of panels.dat differ, while the 4412 and 0012 panels are byte-identical. The 4412 and 16-212 hangs come back from the reference's libm alone; with today's panels the 16-212 sweep hangs at −18° instead of −19°. The 64A010 hang needs both the old panels and the host libm; the other three combinations do not hang.

What was added

  • scripts/xfoil-build.sh --host-libm (also cargo xtask xfoil-build --host-libm, and built on demand) builds target/xfoil-ref/host-libm/{pristine,instrumented}/. These are the two builds without the CORE-MATH objects, and the build fails unless the maths does resolve from the host. host-libm/manifest.txt names the host libm, the OS release and the maths symbols taken from the host. Pristine, instrumented, snan, gcov and proof 3 are untouched.

  • A reproduction bundle per hang, xtask/fixtures-config/reproduce/pathological_<case>_host_libm/. Each holds the panels.dat XFOIL LOADs, the xfoil.inp the pipeline drives it with, and panels.json, which the handoff check reads. The 4412 bundles carry today's panels, which are byte-identical to the old ones. The 16-212 and 64A010 bundles carry yFoil's panels from b448f8d. .gitignore allowlists only the bundles' panels.dat. These are not fixtures: no test reads them, and --audit is unaffected.

  • Two case options in cases.toml:

    • reference = "host-libm" runs the case on the instrumented host-libm build.
    • reproduce = "<bundle>" takes the bundle's panels without running yFoil, and fails if the script generated for the case differs from the bundle's.

    cargo xtask fixtures refuses both outside untracked pathological cases. The manifest records them. cargo xtask coverage skips host-libm copies.

  • Four pathological_…_host_libm copies, following the existing pathological pattern, each pointing at its bundle.

  • Corrected descriptions of the four cases, the 0012 N = 240 case (24° on CORE-MATH, 22° before) and the two existing 4412 pathological copies. The descriptions are quoted on the known-issues run pages, which are updated to match.

  • Reproduction steps. Each affected run page now has a "Reproducing the hang" section. It gives a verification notice (date, yFoil version, the host-libm inputs_fingerprint, host and libm, with an HTML comment marking where the merge commit goes), copy-pasteable commands that need only the host-libm XFOIL, what to expect, the cargo xtask fixtures alternative and a platform caveat. The category-4 page has a summary table after the issue table; the 4.17 text is unchanged.

  • Docs elsewhere: a runbook section in tests/fixtures/README.md, a sentence in category 9, and CLAUDE.md (the build layout, the paragraph after the three proofs, and the pathological group).

Verified from the bundles alone

Each bundle was copied to a fresh .tmp/ directory and run with xfoil < xfoil.inp under the 120 s watchdog. The pristine and the instrumented host-libm builds stopped at the same point. In every run the last iteration prints CD = Infinity and VISCAL: Convergence failed, and XFOIL then never returns. The steps therefore use the pristine build.

Bundle Hangs at VISCAL / SETBL call
4412 Re 1e6 30°, upward leg 31 / 1032
4412 Re 3e6 −24°, downward leg 56 / 1827
16-212 M 0.7 −19°, downward leg 51 / 1205
64A010 TYPE 2 12°, upward leg 13 / 464

How to reproduce

scripts/xfoil-build.sh --host-libm      # gfortran and X11 (macOS: brew install gcc libx11)
mkdir -p .tmp/hang && cp xtask/fixtures-config/reproduce/<case>/{panels.dat,xfoil.inp} .tmp/hang/
cd .tmp/hang && GFORTRAN_UNBUFFERED_ALL=y ../../target/xfoil-ref/host-libm/pristine/bin/xfoil < xfoil.inp
# or: cargo xtask fixtures --case <case>   (the instrumented build; the watchdog marks it truncated_by_watchdog)

The results depend on the host: they were verified on macOS 15.6.1 arm64 with libSystem, and on glibc the same run may take another route.

Checks

cargo build --workspace, cargo clippy --all-targets --all-features -- -D warnings, cargo fmt --check, cargo test --test apparatus, cargo xtask fixtures --audit, ci/no-deviations.sh and scripts/docs.sh build --clean all pass. The build script changed, so the reference fingerprint changes and every stage rebuilds once; the build itself is unchanged.

… stage

Four known-issues sweeps were described as hanging in XFOIL's plot label
(known issues 4.17); the descriptions date from 2026-10-08, when the reference
took its maths from the host libm. On the CORE-MATH reference they do not hang.

- scripts/xfoil-build.sh --host-libm builds target/xfoil-ref/host-libm/: the
  instrumented build without the CORE-MATH objects, failing unless the maths
  does resolve from the host, with its own manifest naming the libm and OS.
  The other stages and proof 3 are unchanged.
- cases.toml takes `reference = "host-libm"` and `panels = <yFoil panels.json
  of an earlier commit>`, both refused outside untracked pathological copies;
  cargo xtask coverage skips host-libm copies.
- Four pathological `_host_libm` copies recreate the hangs; the 64A010 one also
  needs yFoil's panels from b448f8d, before its generators moved to CORE-MATH.
- The descriptions of the four cases, the NACA 0012 N = 240 case and the two
  existing 4412 pathological copies say what happens on each reference.
- xtask/fixtures-config/reproduce/<case>/ holds the panels.dat XFOIL loads,
  the xfoil.inp that drives it and panels.json, for each of the four
  pathological host-libm copies: today's panels for the two 4412 sweeps, and
  yFoil's panels of b448f8d for the 16-212 and 64A010 sweeps. The 64A010
  panels.json moves here from fixtures-config/panels/; .gitignore allowlists
  the bundles' panels.dat only.
- The case option `reproduce = "<bundle>"` replaces `panels`: the pipeline
  takes the bundle's panels without running yFoil, and fails if the script it
  generates differs from the bundle's.
- --host-libm builds host-libm/pristine and host-libm/instrumented, so a hang
  can be repeated on the pristine build with XFOIL alone.
- The 16-212 copy, now on the panels of then, hangs at -19 deg (call 51).
@thclark
thclark merged commit 44ae19f into main Oct 26, 2026
6 checks passed
@thclark
thclark deleted the host-libm-hangs branch October 27, 2026 15:45
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.

1 participant