Replace Ractor.check_isolation with RUBY_RACTOR_CHECK_ISOLATION - #1055
Merged
yaroslav-shopify merged 6 commits intoSep 18, 2026
Merged
yaroslav-shopify merged 6 commits into
yaroslav-shopify merged 6 commits into
Conversation
Trigger the isolation check from a boolean environment variable read once at boot instead of from a method call, so an application can be swept for worker-Ractor incompatibilities without editing every Ractor.new call site. Under the variable every non-main Ractor behaves the way check_isolation did: the Proc is not isolated, arguments and the return value pass by reference, and violations are downgraded to :ractor_isolation warnings. Read the variable the way RUBY_RACTOR_EXCLUSIVE is read and relocate the one-shot advisory to boot, keeping its suppression under exclusive mode. Replace the per-Ractor isolation_check field with the process-wide flag. The three sites in thread.c run in the parent's context while creating the child, so they test the flag directly rather than the shared predicate, which evaluates the current Ractor and would never fire from the main one. Because the flag is process-wide it also covers nested Ractors, which previously reverted to raising, so the test asserting that is inverted and a companion pins that Ractor.new still raises when the variable is unset.
Downgrading the isolation violation to a warning left rb_fork_ruby falling through into the fork it had just reported, because rb_raise is NORETURN and rb_ractor_isolation_violation is not. A sweep of an application that calls fork therefore forked, where the same application previously raised Ractor::IsolationError. fork keeps only the calling thread, so the child inherited a VM whose other Ractors' threads were gone while their objspaces were still mapped. Refuse the fork after warning and report it as a failed one: proc_fork_pid turns -1 into rb_sys_fail, rb_daemon returns -1, and the --help pager stops paging.
RUBY_RACTOR_EXCLUSIVE only engages when USE_MN_THREADS is set, so on a non-MN build the advisory correctly still prints and the unconditional zero-advisory assertion would fail. Branch on the +MN marker in RUBY_DESCRIPTION, asserting suppression where exclusive engages and advisory presence where it cannot.
The fall-through to rb_proc_ractor_make_shareable re-reports the same violation, warned in check mode, so the upstream report is skipped there to avoid warning twice. Flagged as suspicious by two review passes; document it at the site.
The advisory announces a mode that changes process behavior, so it must not be silenced by verbosity flags. Kernel.warn in the deleted method form printed under -W0; the relocated rb_warn did not. Use fprintf.
Under RUBY_RACTOR_CHECK_ISOLATION a hot violation warns on every hit, burying the sweep output. Key each warning on the violation's format string and Ruby call site, print the first, and count the rest into a one-line summary at process exit. The raising path is unchanged.
yaroslav-shopify
merged commit Sep 18, 2026
3463786
into
Shopify:ractor-check-isolation
108 of 128 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces
Ractor.check_isolation(*args) { }with a process-wide environment variable,RUBY_RACTOR_CHECK_ISOLATION, so an application can be swept for Ractor-isolation violations by booting under the variable — no call-site edits.What changes
RUBY_RACTOR_EXCLUSIVE(atoi > 0, same two files). When set, everyRactor.newbehaves asRactor.check_isolationdid: the Proc is not isolated, arguments and return value pass by reference, and isolation violations are downgraded to:ractor_isolationwarnings.Ractor.check_isolationis removed; the env var is the only entry point.RUBY_RACTOR_EXCLUSIVE=1engages) moves to boot and now survives-W0.EPERM) instead of producing a child whose VM lost its other Ractors' threads while their objspaces stay mappedractor_shareable_proc's check-mode guard documented — it prevents a double warning, since the fall-through torb_proc_ractor_make_shareablere-reports the same violationSemantics
Ractor.newinside a check Ractor is also a check Ractor (the flag is process-wide).1on,true/yesoff.Testing
test/ruby/test_ractor.rbmigrated to the env var, including regression tests for the fork refusal and the boot advisorymake btest: 2066 PASS;make test-all: 36539 tests, 0 failures, 0 errors