Skip to content

test(runtime): dead_owner_side_tables races with itself — 15 failures in 200 filtered runs on main #7975

Closed

Description

@proggeramlug

Summary

gc::tests::dead_owner_side_tables has its own intra-module race, in the same
family as #7946/#7955: two of its cases fail ~7 % of runs when the module's
tests are co-scheduled, and the failure is present on origin/main and is NOT
caused by #7974.

Reproduce (release build of the perry-runtime lib test binary):

perry_runtime --test-threads=10 dead_owner_side_tables
binary runs failed
origin/main @ a769fafc6 200 15
the same tree with #7974 applied 200 14

i.e. unchanged by #7974 — filed so nobody mis-attributes it to that PR.

Failing cases and messages:

  • test_dead_arguments_object_entry_pruned_on_full_gc
    (dead_owner_side_tables.rs:488) — the common one:
    dead arguments object's ARGUMENTS_OBJECTS entry must be pruned
    (one insert per call of any function referencing `arguments`)
    
  • test_dead_owner_descriptor_entries_pruned_on_full_gc
    (dead_owner_side_tables.rs:280), less often.

Why it does not show at CI's parallelism

Both arms of a full-suite run are clean: 300 runs of the unfiltered binary
at libtest's default parallelism gave 0 failures on either binary. libtest
spreads a 2 200-test suite out enough that these particular cases rarely land
together. Filtering to the module packs them onto 10 threads and the rate jumps
to ~7 %. So this is currently latent rather than merge-blocking — but it is the
same defect class, and anyone bisecting with a --filter will hit it and
believe their change caused it.

Likely shape (not confirmed)

Both cases assert that an owner with NO roots is dead at a full collection, and
both take GcTestIsolationGuard. The other tests in the module run collections
and install/clear address-keyed side-table entries concurrently
(ARGUMENTS_OBJECTS, PROPERTY_DESCRIPTORS, ACCESSOR_DESCRIPTORS), so the
suspects are the usual two: a concurrent collection on another thread
completing the prune before/after this thread's full_gc(), or an address
recycled into a sibling test's allocation between the plant and the assert.

The #7954/#7974 remedy applies if it holds: the prune algebra is a function of
(side table, valid-pointer set), so it can be driven on tables the test owns,
with the shipped registration pinned read-only.

Acceptance

≥ 200 consecutive --test-threads=10 dead_owner_side_tables runs green, with
the full suite at default parallelism unchanged.

Activity

  1. proggeramlug commented on Aug 12, 2026

    @proggeramlug
    ContributorAuthor

    Root-caused and fixed in #7987; the product defect it was sitting on is #7988.

    It is not a race. Every test in the module already takes the same global isolation mutex, so no two of them ever overlap. Run alone, both named cases fail 200/200 on origin/main; they pass only when a sibling runs first, and --test-threads=10 makes which test goes first nondeterministic — hence the ~5-7%.

    Mechanism: both cases reach an API that resolves the process-global memoized Object.prototype address (array::prototype_addr), and a miss runs the whole lazy globalThis bootstrap (~1.15 MB allocated, ~410 KB live) inside the caller. Arena block reset is all-or-nothing, so mark_block_persisting_arena_objects then force-marks every object in that block, the test's unrooted owner included — and the prune correctly declines, because a persisting block cannot recycle the address. The test failed on the prune and named the prune.

    The cache misses exactly once per process while the bootstrap is per thread, which is both why the schedule decides who pays and why #7988 exists.

  2. added 4 commits that reference this issue on Aug 12, 2026
    23a8aad
    3052a1a
    3a190f0
    3c95020
  3. added 4 commits that reference this issue on Sep 22, 2026
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