Skip to content

test_gap_zlib_4917_level: js_zlib_deflate_raw_sync link failure does not reproduce under perry-dev — profile/dead-strip dependent, not a host flake #7522

Closed

Description

@proggeramlug

What was reported

test_gap_zlib_4917_level fails on main as a link failure —
js_zlib_deflate_raw_sync undefined, even though the symbol is present in the
harness-built archive. Filed originally inside #7518 as a suspected host-local
flake.

It does not reproduce under perry-dev — so it is profile-dependent, not flaky

Same host, Node 26.5.1 oracle, own --profile perry-dev build of
-p perry -p perry-runtime -p perry-stdlib -p perry-runtime-static -p perry-stdlib-static
at every point, object cache cleared between points, PERRY_RUNTIME_DIR pinned at
the freshly built archives:

commit date verdict
17c0ff952 2026-07-30 PASS
c6ed8175d 2026-07-30 PASS
33acba4c1 (main) 2026-08-06 PASS

For contrast, test_gap_diagchannel_3082_3084_3085_3086 (filed separately) does
reproduce under the same perry-dev arm at main. So the arm is capable of
catching a real regression; this one it does not see.

The failure was observed under the release-profile harness
(run_parity_tests.sh builds --release). perry-dev is opt-level=1,
codegen-units=16, incremental, no LTO; release is thin LTO,
codegen-units=1, opt-level=3, strip. An undefined symbol that is present in
the archive is a dead-strip symptom, and dead-strip is exactly what changes
between those two.

Strongest lead

js_zlib_deflate_raw_sync is referenced only from codegen-emitted .o files,
never from within perry-stdlib itself. The #[used] static KEEP_ZLIB_FFI anchor
at crates/perry-stdlib/src/zlib.rs:223 exists precisely to survive
whole-program LTO — its comment cites the same failure mode (#5437 /
project_autoopt_ffi_symbol_link_break: "the auto-optimize whole-program LTO
therefore dead-strips them from the stdlib archive, breaking the link of any
program that uses zlib"). An anchor that holds without LTO and stops holding with
it presents exactly as reported.

Worth checking first, in order:

  1. size: gate keepalive anchors out of the classic link + opt-in size-optimized runtime rebuild (hello world 5.9→4.6 MB default, 2.3 MB size mode) #6917 / ea9c5afa5 gated keepalive anchors out of the classic link and
    added an opt-in size-optimized runtime rebuild. perry-runtime's
    keepalive-anchors feature is default-on and several anchors are
    #[cfg(feature = "keepalive-anchors")], but KEEP_ZLIB_FFI (in
    perry-stdlib) is unconditional — the two are not gated alike, and a
    link that drops one set but not the other is worth ruling in or out.
  2. A stale or partial libperry_stdlib.a in the failing arm. Build outputs
    are invisible to git status, and cargo build -p perry-stdlib does not
    emit the .a — only -p perry-stdlib-static does. Confirm the .a mtime
    moved after the build before believing the arm.
  3. Object-cache reuse across differently-built compilers
    (node_modules/.cache/perry/objects).

Reproduce it properly before bisecting

cargo build --release -p perry -p perry-runtime -p perry-stdlib \
  -p perry-runtime-static -p perry-stdlib-static
# confirm libperry_stdlib.a mtime moved AFTER the build, then:
./run_parity_tests.sh --filter test_gap_zlib_4917_level

Do not use CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16 here — parity work needs
codegen-units=1 (known release-runtime miscompile at cu=16).

If it reproduces under --release but not perry-dev, the delta is LTO /
dead-strip and the fix is a link/anchor one, not a source regression. If it does
not reproduce there either, the original observation was environmental and this
can be closed.

Split out of #7518, where three gap failures were initially misfiled as
host-local flakes on the mistaken reasoning that reproducing on clean main
implied a host quirk (for the EventTarget one it implied an older unnoticed
regression, bisected to c6ed8175d).

Activity

  1. proggeramlug commented on Aug 6, 2026

    @proggeramlug
    ContributorAuthor

    Release-arm evidence, which is what this issue asked for.

    The gap suite ran to completion on the pinned quiet mini (perry-macos.local, node 26.5.1, main @ v0.5.1292) using scripts/run_gap_tests.sh, which builds the compiler --release. test_gap_zlib_4917_level fails there as COMPILE_FAIL — so it reproduces under release on a second, independent host.

    That confirms the reading in this issue: the failure is profile-dependent, not host-dependent and not a flake. perry-dev has no LTO, which is why it passes there; the release arm dead-strips js_zlib_deflate_raw_sync despite its presence in the archive, exactly the mode KEEP_ZLIB_FFI (perry-stdlib/src/zlib.rs:223) exists to prevent.

    Full run for context: 467 parity pass, 18 parity fail, 1 compile fail (this), 1 crash (filed separately as #7526). Only three failures were outside the snapshot: #7518 (fixed by #7520), #7521, and this one.

  2. proggeramlug commented on Aug 10, 2026

    @proggeramlug
    ContributorAuthor

    Re-checked under --release, as this issue asks. The link failure does not reproduce there, so the profile/dead-strip hypothesis this issue was built on is not confirmed.

    Method — same run that settled #7523, at main @ 0a2bf15bd:

    • own cargo build --release (thin LTO, codegen-units=1, opt-level=3, strip) of -p perry -p perry-runtime-static -p perry-stdlib-static. Deliberately not CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16: dead-strip behaviour is exactly what that shortcut would change, so it would have measured the wrong linker input;
    • PERRY_RUNTIME_DIR pinned at the freshly built archives, mtimes confirmed;
    • Node 26.5.1 oracle.
    configuration result
    --release, single test, 3 runs PASS 3/3
    --release, full 522-test parallel sweep PASS

    js_zlib_deflate_raw_sync linked every time. The full-sweep result is the one that matters: the failure was reported from the parallel harness, and this is that harness on that profile.

    On the "strongest lead" in the issue body — I checked it directly. js_zlib_deflate_raw_sync is present in the #[used] static KEEP_ZLIB_FFI anchor at crates/perry-stdlib/src/zlib.rs, one of 21 entries, so the anchor that exists to survive whole-program LTO already covers this symbol. There is no missing-anchor bug to fix here.

    Closing as not reproducing. Worth recording for the next sighting: an undefined symbol that is present in the archive is still a real shape (that is what #5437 was), so if this returns, capture the failing link line and whether the archive in PERRY_RUNTIME_DIR was the one the harness had just built — the auto-optimizer relinks a feature-stripped runtime (features=async-runtime,web-fetch, no diagnostics) and that relinked archive, not the built one, is what a program can end up linking against.

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