Skip to content

Incremental GC verifier finds a reachable object left unmarked in gc_stress #424

Open

Description

@dimensionscape

The opt-in incremental collector left a reachable object unmarked in the gc stress test, and the verifier (HXCPP_GC_INCREMENTAL_VERIFY) aborted the run. It happened once, on the Haxe 4.3.7 / Linux 64 / incremental gc job:

https://github.com/openfl/libhxcpp/actions/runs/41359125947/job/125006688889

gc stress: 30 s, 8 threads, seed 2012663045
Incremental GC omitted reachable object 0x7f942007ef30 flags=12800801 epoch=23000000 rows=1 first=1 vtable=0x5597e36ca850
Aborted (core dumped) bin/Stress 30 8 2012663045

That is test/gc_stress built with -D HXCPP_GC_INCREMENTAL -D HXCPP_GC_INCREMENTAL_VERIFY, run as in test.yml. The abort came about 8.5 seconds into the 30 second run, not at exit.

Reading the header:

  • The object is a container (0x00800000), one row long, and its line is marked.
  • Its mark ID is 0x12, while the current one is 0x23, so the incremental cycle that just finished never reached it, though a stop-the-world walk from the roots did.

If the collector had gone on without the verifier, the object would have been swept while still reachable.

The seed is fixed, but with 8 threads the run isn't repeatable, and this job has passed on every recent main run, so it's intermittent. The run was on a branch whose only runtime change is at process exit (#423), which wasn't active yet at that point. I haven't reproduced it locally yet.

Activity

  1. dimensionscape commented on Nov 2, 2026

    @dimensionscape
    MemberAuthor

    It happened again on the next run, this time on Windows 64 with the big blocks variant (-D HXCPP_GC_BIG_BLOCKS, seed 1337), less than a tenth of a second into the run:

    https://github.com/openfl/libhxcpp/actions/runs/41375157695/job/125055392989

    gc stress: 30 s, 8 threads, seed 1337
    Incremental GC omitted reachable object 000001FBD125FF88 flags=21800a01 epoch=12000000 rows=1 first=1 vtable=00007FF629304D58
    

    The pattern is the same as before: a one row container with its line marked, carrying a mark ID from an older cycle.

    It reproduces locally on Windows with MSVC, running bin/Stress 3 8 1337 built with -D HXCPP_GC_INCREMENTAL -D HXCPP_GC_INCREMENTAL_VERIFY -D HXCPP_GC_BIG_BLOCKS -D HXCPP_M64. The failure rate is about 1 in 75 runs:

    So it's on main and not related to that branch.

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