Found while re-running #7803's workload on bdfcba4a2 (v0.5.1499), now that the
zod dependency corpus links again (#7980).
What happens
test-files/gc-dep-corpus/main.ts under a rate-1 seeded schedule aborts with
exit 134 and the runtime's own latch report:
[gc-pin-latch] FATAL: copying minor is about to relocate a PINNED young object
on a preflight-skipped cycle. header=0x2db2f681350 obj_type=8 size=731 flags=0x37
The young-pin latch (gc/pin.rs) is incomplete: some site sets GC_FLAG_PINNED
without going through gc::pin_object. Find it with `python3 scripts/gc_pin_sites.py`
and route it through pin_object (#7645).
[gc-schedule] FAILURE (signal 6) under seed=15
[gc-schedule] safepoints=1870 scheduled_collections=1870
This is crates/perry-runtime/src/gc/copying.rs:691 — the latch #7645 added on
purpose — firing. So this is a detected fault, not a silent one, which is
the latch working as designed.
Reproduce
cargo build --release -p perry -p perry-runtime-static -p perry-stdlib-static
npm ci --ignore-scripts --no-audit --no-fund
PERRY_RUNTIME_DIR=target/release PERRY_NO_AUTO_OPTIMIZE=1 PERRY_DISABLE_BUILD_CACHE=1 \
target/release/perry test-files/gc-dep-corpus/main.ts -o /tmp/w
RATE=1 TIMEOUT=1800 PERRY_GC_PROTECT_FROMSPACE=0 PERRY_GC_DIAG=1 \
./scripts/gc_schedule_fuzz.sh /tmp/w 16
It is intermittent. Seed 15 aborted once in a 16-seed sweep and then passed
3/3 on re-run with the identical command, so do not treat a passing seed 15 as a
refutation — the seeded schedule does not replay exactly on this workload
(safepoints drifts ~4% run to run at a fixed seed). Budget a sweep, not a run.
What the header says
obj_type=8 = GC_TYPE_MAP. The corpus keeps its registry in Maps
(SCHEMAS / CALLBACKS in test-files/gc-dep-corpus/shared.ts), walked by
parseRegistered().
size=731.
flags=0x37 = MARKED | ARENA | PINNED | INTERNED | TENURED. Worth a second
look on its own: TENURED is set on an object the copying minor is treating
as young.
The FATAL's own remediation does not apply
The message says to find a site that sets GC_FLAG_PINNED without going through
gc::pin_object. On this tree that tool disagrees:
$ python3 scripts/gc_pin_sites.py
gc_pin_sites: OK — every pin originates in gc::pin_object
(2 allowlisted exception(s), 56 GC_FLAG_PINNED tokens scanned).
So either one of the two allowlisted exceptions is responsible, or the pin is
legitimate and the defect is in the preflight-skip decision
(Self::preflight_walks_decided, copying.rs:1111) rather than in pin
bookkeeping. Either way the printed remediation currently sends the reader at a
hypothesis its own tool refutes, and should be reworded once the cause is known.
#7645 is closed, hence a new issue rather than a reopen.
Scope note
This is not the #7154-class rooting failure that the same sweep also
produces on other seeds (TypeError: value is not a function,
Cannot read properties of undefined) — those surface cycles later with nothing
for the collector to find, whereas this one is caught at the instant of the
move. Triage of the whole sweep is in gc-handoff/ZOD-NOTES.md (#7989).
Found while re-running #7803's workload on
bdfcba4a2(v0.5.1499), now that thezod dependency corpus links again (#7980).
What happens
test-files/gc-dep-corpus/main.tsunder a rate-1 seeded schedule aborts withexit 134 and the runtime's own latch report:
This is
crates/perry-runtime/src/gc/copying.rs:691— the latch #7645 added onpurpose — firing. So this is a detected fault, not a silent one, which is
the latch working as designed.
Reproduce
It is intermittent. Seed 15 aborted once in a 16-seed sweep and then passed
3/3 on re-run with the identical command, so do not treat a passing seed 15 as a
refutation — the seeded schedule does not replay exactly on this workload
(
safepointsdrifts ~4% run to run at a fixed seed). Budget a sweep, not a run.What the header says
obj_type=8=GC_TYPE_MAP. The corpus keeps its registry inMaps(
SCHEMAS/CALLBACKSintest-files/gc-dep-corpus/shared.ts), walked byparseRegistered().size=731.flags=0x37=MARKED | ARENA | PINNED | INTERNED | TENURED. Worth a secondlook on its own:
TENUREDis set on an object the copying minor is treatingas young.
The FATAL's own remediation does not apply
The message says to find a site that sets
GC_FLAG_PINNEDwithout going throughgc::pin_object. On this tree that tool disagrees:So either one of the two allowlisted exceptions is responsible, or the pin is
legitimate and the defect is in the preflight-skip decision
(
Self::preflight_walks_decided,copying.rs:1111) rather than in pinbookkeeping. Either way the printed remediation currently sends the reader at a
hypothesis its own tool refutes, and should be reworded once the cause is known.
#7645 is closed, hence a new issue rather than a reopen.
Scope note
This is not the #7154-class rooting failure that the same sweep also
produces on other seeds (
TypeError: value is not a function,Cannot read properties of undefined) — those surface cycles later with nothingfor the collector to find, whereas this one is caught at the instant of the
move. Triage of the whole sweep is in
gc-handoff/ZOD-NOTES.md(#7989).