Skip to content

Add Ractor.check_isolation - #1040

Open
hmcguire-shopify wants to merge 1 commit into
masterfrom
ractor-check-isolation
Open

Add Ractor.check_isolation#1040
hmcguire-shopify wants to merge 1 commit into
masterfrom
ractor-check-isolation

Conversation

@hmcguire-shopify

Copy link
Copy Markdown

Run the block in a real non-main Ractor while preserving its closure and argument identities. Downgrade isolation violations to categorized warnings so applications can sweep worker-Ractor compatibility without stopping at the first failure.

Support an exclusive scheduler mode for race-free checks and cover the isolation gates, fast paths, messaging, and thread inheritance.

@hmcguire-shopify

Copy link
Copy Markdown
Author
Sol's Review

 ### 1. Cross-objspace mutation still crashes the VM

 Severity: CRITICAL
 Location: thread.c:628-653, thread.c:963-972

 The check Ractor runs a caller-owned closure in a separate objspace. Writing an object allocated by the check
 Ractor into a caller-owned container creates an edge neither local GC can trace safely.

 Confirmed reproducer:

 ```ruby
   outer = []

   Ractor.check_isolation do
     100_000.times { outer << Object.new }
     GC.start
   end
 ```

 This aborts with try to mark T_NONE object and then segfaults, including under RUBY_RACTOR_EXCLUSIVE=1.

 The same ownership problem applies if the caller waiting on .value is interrupted: the caller-owned Proc and
 arguments may lose their owner-side roots while the hidden Ractor continues. I reproduced an abort after killing
 the waiting Thread, forcing GC, and then resuming the check Ractor.

 Required fix: Introduce an explicit cross-objspace ownership/rooting model, or redesign the special Ractor so
 arbitrary by-reference mutation cannot create these edges. Scheduler serialization alone cannot solve GC
 ownership.

 ### 2. By-reference messages still contain dangling pointers

 Severity: CRITICAL
 Location: ractor_sync.c:1071-1084

 The patch puts arbitrary unshareable objects into basket_type_ref, whose existing lifetime assumptions apply to
 shareable objects. Once queued in another Ractor, no owner-side pin keeps the payload alive.

 Sending a child-created Hash to a main-owned port, dropping the local reference, and forcing GC reliably aborts
 the VM—even in exclusive mode.

 Required fix: Preserve normal copy semantics, or introduce a dedicated borrowed-message representation that pins
 the payload in its owner’s objspace until dequeue or queue destruction.

 ### 3. Exclusive mode does not cover dedicated native threads

 Severity: HIGH
 Location: thread_sched.c:1796-1838

 max_cpu = 1 limits shared native threads. A thread promoted through rb_thread_lock_native_thread leaves that
 count, allowing a replacement shared thread to execute while the dedicated thread continues.

 The documentation now discloses this limitation, but it means the mode still cannot provide the safety guarantee
 needed for arbitrary by-reference execution.

 Required fix: Add a VM-wide Ruby-execution permit honored by both shared and dedicated native threads, with a
 native-thread regression test.

 ### 4. Warning traffic remains unbounded

 Severity: MEDIUM
 Location: ractor.c:4050-4068, vm_insnhelper.c:1142-1148

 A hot offending access emits a synchronous warning on every iteration. A large sweep can generate enormous stderr
 traffic or exhaust memory in a custom Warning.warn collector.

 Recommended fix: Deduplicate by violation kind and call site, or impose a per-check warning budget followed by a
 suppressed-count summary.

Run the block in a real non-main Ractor while preserving its closure and
argument identities. Downgrade isolation violations to categorized warnings
so applications can sweep worker-Ractor compatibility without stopping at
the first failure.

Support an exclusive scheduler mode for race-free checks and cover the
isolation gates, fast paths, messaging, and thread inheritance.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants