Skip to content

Conversation

@pull
Copy link

@pull pull bot commented Nov 19, 2025

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 : )

jhawthorn and others added 16 commits November 18, 2025 17:02
Previously any T_OBJECT with >= 94 IVARs would crash during compaction
attempting to make an object too large to embed.
This is useful, in case you're using Docker, and an upstream
Dockerfile sets BUNDLER_VERSION to something you don't want.
It's impossible to unset it... only override to be the empty
string.

ruby/rubygems@ffa3eb9ac6
- In ruby/rubygems@31d67ec
  we enforced the new behaviour where running `bundle` no longer
  installs gems but displays the help.
  Users now have a way to configure their preferred default command using
  the `BUNDLE_DEFAULT_CLI_COMMAND` flag.

  With the preview of Ruby 4.0 now being released, some people will
  start to see this new change.

  The problem is that the previous behaviour had existed for like an
  eternity and we didn't warn users about this change in advance.
  I'd like to provide a deprecation/warning cycle because this is
  confusing users already and this breaks various CI setup that now
  needs to be changed immediately.

ruby/rubygems@e415480ac5
Visual C++ 2005 (8.0):
- _MSC_VER: 1400
- MSVCRT_VERSION: 80
Visual C++ 2008 (9.0):
- _MSC_VER: 1500
- MSVCRT_VERSION: 90
Visual C++ 2010 (10.0):
- _MSC_VER: 1600
- MSVCRT_VERSION: 100
Visual C++ 2013 (12.0):
- _MSC_VER: 1800
- MSVCRT_VERSION: 120
Visual C++ 2015 (14.0):
- _MSC_VER: 1900
- MSVCRT_VERSION: 140
We need the VM barrier in rb_gc_impl_before_fork to stop the other Ractors
because otherwise they could be allocating objects in the fast path which
could be calling mmtk_add_obj_free_candidate. Since mmtk_add_obj_free_candidate
acquires a lock on obj_free_candidates in weak_proc.rs, this lock may not
be released in the child process after the Ractor dies.

For example, the following script demonstrates the issue:

    puts "Hello #{Process.pid}"

    100.times do |i|
      puts "i = #{i}"
      Ractor.new(i) do |j|
        puts "Ractor #{j} hello"
        1000.times do |i|
          s = "#{j}-#{i}"
        end
        Ractor.receive
        puts "Ractor #{j} goodbye"
      end
      pid = fork { }
      puts "Child pid is #{pid}"
      _, status = Process.waitpid2 pid
      puts status.success?
    end

    puts "Goodbye"

In the child process, we can see that it is stuck trying to acquire the
lock on obj_free_candidates:

    #5  0x00007192bfb53f10 in mmtk_ruby::weak_proc::WeakProcessor::get_all_obj_free_candidates (self=0x7192c0657498 <mmtk_ruby::BINDING+72>) at src/weak_proc.rs:52
    #6  0x00007192bfa634c3 in mmtk_ruby::api::mmtk_get_all_obj_free_candidates () at src/api.rs:295
    #7  0x00007192bfa61d50 in rb_gc_impl_shutdown_call_finalizer (objspace_ptr=0x578c17abfc50) at gc/mmtk/mmtk.c:1032
    #8  0x0000578c1601e48e in rb_ec_finalize (ec=0x578c17ac06d0) at eval.c:166
    #9  rb_ec_cleanup (ec=<optimized out>, ex=<optimized out>) at eval.c:257
    #10 0x0000578c1601ebf6 in ruby_cleanup (ex=<optimized out>) at eval.c:180
    #11 ruby_stop (ex=<optimized out>) at eval.c:292
    #12 0x0000578c16127124 in rb_f_fork (obj=<optimized out>) at process.c:4291
    #13 rb_f_fork (obj=<optimized out>) at process.c:4281

ruby/mmtk@eb4b229858
In rb_gc_impl_before_fork, it locks the VM and barriers all the Ractors
before calling mmtk_before_fork. However, since rb_mmtk_block_for_gc is
a barrier point, one or more Ractors could be paused there. However,
mmtk_before_fork is not compatible with that because it assumes that the
MMTk workers are idle, but the workers are not idle because they are
busy working on a GC.

This commit essentially implements a trylock. It will optimistically
lock but will release the lock if it detects that any other Ractors are
waiting in rb_mmtk_block_for_gc.

For example, the following script demonstrates the issue:

    puts "Hello #{Process.pid}"

    100.times do |i|
      puts "i = #{i}"
      Ractor.new(i) do |j|
        puts "Ractor #{j} hello"
        1000.times do |i|
          s = "#{j}-#{i}"
        end
        Ractor.receive
        puts "Ractor #{j} goodbye"
      end
      pid = fork { }
      puts "Child pid is #{pid}"
      _, status = Process.waitpid2 pid
      puts status.success?
    end

    puts "Goodbye"

We can see the MMTk worker thread is waiting to start the GC:

    #4  0x00007ffff66538b1 in rb_mmtk_stop_the_world () at gc/mmtk/mmtk.c:101
    #5  0x00007ffff6d04caf in mmtk_ruby::collection::{impl#0}::stop_all_mutators<mmtk::scheduler::gc_work::{impl#14}::do_work::{closure_env#0}<mmtk::plan::immix::gc_work::ImmixGCWorkContext<mmtk_ruby::Ruby, 0>>> (_tls=..., mutator_visitor=...) at src/collection.rs:23

However, the mutator thread is stuck in mmtk_before_fork trying to stop
that worker thread:

    #4  0x00007ffff6c0b621 in std::sys::thread::unix::Thread::join () at library/std/src/sys/thread/unix.rs:134
    #5  0x00007ffff6658b6e in std::thread::JoinInner<()>::join<()> (self=...)
    #6  0x00007ffff6658d4c in std::thread::JoinHandle<()>::join<()> (self=...)
    #7  0x00007ffff665795e in mmtk_ruby::binding::RubyBinding::join_all_gc_threads (self=0x7ffff72462d0 <mmtk_ruby::BINDING+8>) at src/binding.rs:115
    #8  0x00007ffff66561a8 in mmtk_ruby::api::mmtk_before_fork () at src/api.rs:309
    #9  0x00007ffff66556ff in rb_gc_impl_before_fork (objspace_ptr=0x555555d17980) at gc/mmtk/mmtk.c:1054
    #10 0x00005555556bbc3e in rb_gc_before_fork () at gc.c:5429

ruby/mmtk@1a629504a7
Ruby 2.7 supports MSVC 12.0/_MSC_VER 1800 or later.

ruby/etc@6f4404ec88
Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@08c6903...93cb6ef)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 5.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
@pull pull bot locked and limited conversation to collaborators Nov 19, 2025
@pull pull bot added the ⤵️ pull label Nov 19, 2025
@pull pull bot merged commit 1443f89 into turkdevops:master Nov 19, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants