Skip to content

Flaky CI: FinalizationRegistry callback crashes during process shutdown #661

@krodak

Description

@krodak

Problem

testJSWrapperIsDeallocatedAfterFinalization intermittently crashes in CI with:

RuntimeError: memory access out of bounds
    at _swift_release_dealloc
    at swift_nonatomic_release
    at swift_release
    at $s20BridgeJSRuntimeTests19_bjs_Greeter_deinityySvF
    at bjs_Greeter_deinit
    at swiftHeapObjectFinalizationRegistry (bridge-js.js)
    at FinalizationRegistry.cleanupSome (<anonymous>)

Sometimes the error is table index is out of bounds instead of memory access out of bounds, but the stack is identical.

Frequency

Examples from main:

Also hits PRs with no related changes (e.g. #656).

Origin

Introduced in #648 (merged Feb 18), which added the shared swiftHeapObjectFinalizationRegistry and the testJSWrapperIsDeallocatedAfterFinalization test. The first failure was the very next CI run after that merge (run 22134917335, commit b10bee6).

The hasReleased guard added in that PR prevents double-release, but doesn't protect against calling into Wasm after the instance's memory is no longer valid.

Root cause

After all tests complete, Node.js starts shutting down and V8 GC collects remaining SwiftHeapObject JS wrappers. The FinalizationRegistry callback fires and calls state.deinit(state.pointer), which is a Wasm export (bjs_Greeter_deinit). That calls Unmanaged<Greeter>.fromOpaque(pointer).release(), which triggers swift_release -> _swift_release_dealloc.

At this point the Wasm linear memory or function table is already in an invalid state (the Swift runtime may have already run its own cleanup during process teardown), so the release crashes.

The test itself explicitly triggers GC and waits for finalization in a loop (lines 48-56 of SwiftClassSupportTests.swift). The non-deterministic part is whether GC runs the finalizer before or after Wasm teardown begins.

Environment

  • Node.js v20.20.0 on ubuntu-22.04
  • Swift 6.1 release toolchain

Metadata

Metadata

Assignees

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