[pull] master from ruby:master#1212
Merged
Merged
Conversation
coroutine_thread_terminated designated the successor first (thread_sched_to_dead_common) and only then removed the dying thread from the living set. The removal's VM-lock work (ractor_check_blocking and a possible barrier join) then ran detached: the thread had already left the running set while sched.running pointed to the successor. Such a joiner corrupts the successor's saved machine context (RB_VM_SAVE_MACHINE_CONTEXT captures the executing thread's state but the join parked cr->threads.sched.running), can sleep on an already-completed barrier until the NEXT one completes (a hang at process exit), is mis-counted in barrier_waiting_cnt, and races ractor_check_blocking's stale will-block decision. Do the removal first, while the thread still owns the Ractor's scheduler slot: the VM-lock work runs as an ordinary counted running thread and the whole class of detached races disappears. After the removal th may be unreachable, but no GC can complete while th still owns the slot (a barrier waits for it to join), so the short handoff tail may keep touching th/sched. The Ractor's last thread keeps the original reverse order: its removal unlinks the Ractor itself, so r/sched must not be touched afterwards. That order is safe only for it: with no successor, sched->running stays NULL and vm_need_barrier requires a running thread, so its removal's VM lock never joins a barrier in the first place. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The is_running check added by 3fa1c87 guarded against a terminating thread joining the barrier after leaving the running set. Since the previous commit such a thread leaves the living set before handing over its scheduler slot, so every joiner is a running-set member again. Restore the unconditional count and assert the invariant instead. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Exercises a short-lived thread terminating while another Ractor drives GC.compact barriers, the scenario fixed by the previous commits. Skipped when the GC does not implement compaction (e.g. MMTk). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A fork taken while the parent holds the VM barrier (e.g. rb_gc_before_fork) leaves the child with barrier_waiting set and a barrier owner that no longer exists, so the next barrier in the child could never complete. Reset the barrier fields in thread_sched_atfork like the rest of the scheduler state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Encode the safety argument of the epilogue reorder as VM_ASSERTs: a non-last dying thread still owns its scheduler slot when it leaves the living set (its VM-lock work stays a counted running thread), and the last thread's reverse order is only safe because it has no successor (running == NULL, so the removal cannot join a barrier). Also check winding_cnt against underflow at the reclaim decrement. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ractor_port_receive/send derive a raw 'struct ractor_port *rp' from self's embedded (RUBY_TYPED_EMBEDDABLE) data and keep using it across a GC safepoint: receive parks, and send allocates the basket. self is only kept alive movably (rb_gc_mark_movable via the VM stack), so a concurrent GC.compact can relocate the port and leave rp dangling -- the receiver then polls a stale, reused slot's port id forever (a hang of Ractor#value under IO + GC.compact). RB_GC_GUARD(self) keeps self on the machine stack, whose conservative scan pins the port so it cannot move while rp is live.
Forking with live Ractors takes a VM barrier in the parent and the child inherits scheduler/barrier state that must be reset. General regression coverage for the parent-side fork barrier and the child teardown, checking the surviving Ractors still work afterwards. (Uses GC.start, not GC.compact, so it also runs on GCs without compaction such as MMTk.)
Instead of spilling into a raw buffer, `RObject` now spills
into an `IMEMO/fields` object like other types.
From an instance variable layout standpoint, an extended `RObject`
is now identical to a `RTypedData`, as in they both store the
reference to their `IMEMO/fields` at the same offset (`VALUE * 2`).
One positive consequence of this is that the only case where a `T_OBJECT`
needs sweeping is if a finalizer was registered.
YJIT now side exit when it need to write a new ivar into a `RObject`
that is out of space. This is unlikely to cause a performance regression
as this codepath isn't supposed to happen after warmup given `max_iv_count`
is recorded on classes, so future objects should be large enough.
Hence it's best not to waste executable memory for such codepath.
ZJIT lost support for writting into extended `RObject`.
Most of the code to support it is there it's just missing an
implementation of `RBASIC_SET_SHAPE_ID`, which recently changed
to strip some bits out of the shape (see comments).
I will leave it to the ZJIT team to implement it (sorry).
There are a few future cleanups planned that I keep for followups:
- We can now get rid of the `ROBJECT_HEAP` flag, it's redundant with
the shape layout bits.
- `imemo_fields` can now embed the `st_table` when complex.
Co-Authored-By: John Hawthorn <john@hawthorn.email>
Co-authored-by: Randy Stauner <randy@r4s6.net>
…efines it RubyGems older than 3.6 has no rubygems/vendored_tsort, and its own Gem::TSort is often already loaded through rubygems/request_set by the time Bundler runs, e.g. from Gem.activate_bin_path in binstubs. The unconditional reassignment printed an already-initialized-constant warning to stderr, breaking specs that assert empty stderr against system RubyGems. The old vendored Gem::TSort is API-compatible, so keep it when present. ruby/rubygems@a42ded1d99 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…RGV=system Since RGV started defaulting to ".", the system-rubygems-bundler job has been silently testing the repo's RubyGems instead of the one shipped with each Ruby, because switch_rubygems is injected into every spec-spawned process. Add an explicit RGV=system mode and set it on the job's test step. The harness itself keeps running on the checked out RubyGems even in this mode. The flattened lib/ contains both Bundler and RubyGems, so it is unavoidably on the harness load path and would get mixed into an older RubyGems otherwise. Only processes spawned by specs boot system RubyGems untouched, which is the configuration under test. ruby/rubygems@40bb5bcd38 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… tsort default gem RubyGems 3.4 and 3.5 ship vendored tsort under its pre-3.6 name rubygems/tsort, so prefer that when rubygems/vendored_tsort is missing. Requiring the real tsort activated the tsort default gem, breaking the guarantee that bundler/setup activates no gems. This mirrors the fallback chain already used by vendored_net_http. ruby/rubygems@7300743bfe Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… older than 4.1 Gem::Installer#remove_stale_plugins only exists since RubyGems 4.1, so installing with no_install_plugin set on an older system RubyGems raised NameError. Reimplement it in Bundler's installer, like generate_plugins already is. ruby/rubygems@d3037ba378 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on under test Under RGV=system the harness runs on the checked out RubyGems while spec-spawned processes run system RubyGems, so rubygems-tagged filters and expectations interpolating Gem::VERSION were checking the wrong version. Capture the system RubyGems version before switching and use it for the rubygems: exclusion filter, version-dependent expectations, and the global gem cache location. The cached git gemspec comparison now serializes with the RubyGems that wrote the file, since Specification#to_ruby output differs across versions. ruby/rubygems@62fa95fe35 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )