Project

General

Profile

Actions

Bug #21848

open

GC compaction freezes during code reload with 100% CPU in rb_vm_ci_free -> st_general_delete

Bug #21848: GC compaction freezes during code reload with 100% CPU in rb_vm_ci_free -> st_general_delete

Added by henrik (Henrik A) 30 days ago. Updated 14 days ago.

Status:
Assigned
Target version:
-
ruby -v:
ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin24]
[ruby-core:124616]

Description

Ruby 4.0.1 freezes with 100% CPU usage when garbage collection runs during Rails code reloading (hot reload in development). The process becomes unresponsive and requires kill -9 to terminate.

Environment:

  • Ruby: 4.0.1 (Homebrew, ARM64)
  • Platform: macOS 15.6.1 (Darwin 24.6.0, Apple Silicon)
  • Rails: 8.x with Puma 7.2.0
  • Mode: Development with code reloading enabled

Steps to reproduce:

  1. Run a Rails application with Puma in development mode (bundle exec rails server -e development -b 0.0.0.0)
  2. Make a several code change to trigger hot reload, reload the site in the browser in between
  3. Process freezes with ~100% CPU

Expected behavior:
Code reloads successfully, GC completes normally.

Actual behavior:
Process freezes indefinitely at 100% CPU. Stack trace from sample shows GC stuck in hash table lookup while freeing VM call info:

  gc_sweep  (in libruby.4.0.dylib)                                                                                                                                                                                                     
    gc_compact_plane                                                                                                                                                                                                                   
      gc_sweep_page                                                                                                                                                                                                                    
        gc_sweep_plane                                                                                                                                                                                                                 
          rb_gc_obj_free_vm_weak_references                                                                                                                                                                                            
            rb_vm_ci_free                                                                                                                                                                                                              
              st_general_delete                                                                                                                                                                                                        
                find_table_bin_ind                                                                                                                                                                                                     
                  vm_ci_hash_cmp  <-- stuck here, spinning                                                                                                                                                                             
                                                                                                                                                                                                                                      

Full relevant stack (Puma worker thread):

  Thread: puma srv tp 005                                                                                                                                                                                                              
    rb_ary_each -> rb_yield -> invoke_block_from_c_bh -> rb_vm_exec                                                                                                                                                                    
      -> int_upto -> rb_yield (nested loops)                                                                                                                                                                                           
        -> vm_search_method_slowpath0 -> rb_vm_search_method_slowpath                                                                                                                                                                  
          -> newobj_of -> newobj_cache_miss -> gc_continue                                                                                                                                                                             
            -> gc_sweep -> gc_compact_plane -> gc_sweep_page                                                                                                                                                                           
              -> gc_sweep_plane -> rb_gc_obj_free_vm_weak_references                                                                                                                                                                   
                -> rb_vm_ci_free -> st_general_delete                                                                                                                                                                                  
                  -> find_table_bin_ind -> vm_ci_hash_cmp                                                                                                                                                                              
                                                                                                                                                                                                                                      

Workaround:
Disabling auto-compaction prevents the freeze:
GC.auto_compact = false

Analysis:
The freeze occurs during GC sweep/compaction when freeing cached VM call info entries (rb_vm_ci_free). This is triggered by code reloading which invalidates method caches. The GC appears to get stuck in an infinite loop or
extremely slow operation in find_table_bin_ind while looking up entries in the call info hash table.


Files

rails_stuck.txt (159 KB) rails_stuck.txt henrik (Henrik A), 01/24/2026 07:15 PM
Actions

Also available in: PDF Atom