ruby/bootstraptest
Peter Zhu f30f0f0a22 Fix crash when instantiating classes in Ractors
[Bug #18119]

When we create classes, it pushes the class to the subclass list of the
superclass. This access needs to be synchronized because multiple Ractors
may be creating classes with the same superclass, which would cause race
conditions and cause the linked list to be corrupted.

For example, we can reproduce with this script crashing:

    workers = (0...8).map do
      Ractor.new do
        loop do
          100.times.map { Class.new }
          Ractor.yield nil
        end
      end
    end

    100.times { Ractor.select(*workers) }

With ASAN enabled, we can see that there are use-after-free errors:

    ==176013==ERROR: AddressSanitizer: heap-use-after-free on address 0x5030000974f0 at pc 0x62f9e56f892d bp 0x7a503f1ffd90 sp 0x7a503f1ffd88
    WRITE of size 8 at 0x5030000974f0 thread T4
        #0 0x62f9e56f892c in rb_class_remove_from_super_subclasses class.c:149:24
        #1 0x62f9e58c9dd2 in rb_gc_obj_free gc.c:1262:9
        #2 0x62f9e58f6e19 in gc_sweep_plane gc/default/default.c:3450:21
        #3 0x62f9e58f686a in gc_sweep_page gc/default/default.c:3535:13
        #4 0x62f9e58f12b4 in gc_sweep_step gc/default/default.c:3810:9
        #5 0x62f9e58ed2a7 in gc_sweep gc/default/default.c:4058:13
        #6 0x62f9e58fac93 in gc_start gc/default/default.c:6402:13
        #7 0x62f9e58e8b69 in heap_prepare gc/default/default.c:2032:13
        #8 0x62f9e58e8b69 in heap_next_free_page gc/default/default.c:2255:9
        #9 0x62f9e58e8b69 in newobj_cache_miss gc/default/default.c:2362:38
    ...
    0x5030000974f0 is located 16 bytes inside of 24-byte region [0x5030000974e0,0x5030000974f8)
    freed by thread T4 here:
        #0 0x62f9e562f28a in free (miniruby+0x1fd28a) (BuildId: 5ad6d9e7cec8318df6726ea5ce34d3c76d0d0233)
        #1 0x62f9e58ca2ab in rb_gc_impl_free gc/default/default.c:8102:9
        #2 0x62f9e58ca2ab in ruby_sized_xfree gc.c:5029:13
        #3 0x62f9e58ca2ab in ruby_xfree gc.c:5040:5
        #4 0x62f9e56f88e6 in rb_class_remove_from_super_subclasses class.c:152:9
        #5 0x62f9e58c9dd2 in rb_gc_obj_free gc.c:1262:9
        #6 0x62f9e58f6e19 in gc_sweep_plane gc/default/default.c:3450:21
        #7 0x62f9e58f686a in gc_sweep_page gc/default/default.c:3535:13
        #8 0x62f9e58f12b4 in gc_sweep_step gc/default/default.c:3810:9
        #9 0x62f9e58ed2a7 in gc_sweep gc/default/default.c:4058:13
    ...
    previously allocated by thread T5 here:
        #0 0x62f9e562f70d in calloc (miniruby+0x1fd70d) (BuildId: 5ad6d9e7cec8318df6726ea5ce34d3c76d0d0233)
        #1 0x62f9e58c8e1a in calloc1 gc/default/default.c:1472:12
        #2 0x62f9e58c8e1a in rb_gc_impl_calloc gc/default/default.c:8138:5
        #3 0x62f9e58c8e1a in ruby_xcalloc_body gc.c:4964:12
        #4 0x62f9e58c8e1a in ruby_xcalloc gc.c:4958:34
        #5 0x62f9e56f906e in push_subclass_entry_to_list class.c:88:13
        #6 0x62f9e56f906e in rb_class_subclass_add class.c:111:38
        #7 0x62f9e56f906e in RCLASS_SET_SUPER internal/class.h:257:9
        #8 0x62f9e56fca7a in make_metaclass class.c:786:5
        #9 0x62f9e59db982 in rb_class_initialize object.c:2101:5
2025-05-09 10:24:38 -04:00
..
pending.rb Moved already resolved test 2020-04-27 10:39:07 +09:00
runner.rb [Feature #21116] Extract RJIT as a third-party gem 2025-02-13 18:01:03 +09:00
test_attr.rb Revert "Revert "This commit implements the Object Shapes technique in CRuby."" 2022-10-11 08:40:56 -07:00
test_autoload.rb Use File.write instead of Kernel#open 2024-07-09 13:01:44 +09:00
test_block.rb
test_class.rb
test_constant_cache.rb Finer-grained constant cache invalidation (take 2) 2022-04-01 14:48:22 -04:00
test_env.rb
test_eval.rb Raise a compile error for break/next/redo inside eval in cases where it is optimized away 2024-09-18 16:54:56 -07:00
test_exception.rb Do not include a backtick in error messages and backtraces 2024-02-15 18:42:31 +09:00
test_fiber.rb support concurrent btest execution 2022-02-06 03:05:47 +09:00
test_finalizer.rb Test finalizer is ran in bootstraptest 2024-04-01 10:26:16 -04:00
test_flip.rb
test_flow.rb Ensure test suite is compatible with --frozen-string-literal 2024-03-14 17:56:15 +01:00
test_fork.rb Fail test if child process exists non-zero 2025-03-25 19:14:26 -07:00
test_gc.rb [Feature #21116] Extract RJIT as a third-party gem 2025-02-13 18:01:03 +09:00
test_insns.rb Optimize instructions when creating an array just to call include? (#12123) 2024-11-26 14:31:08 -05:00
test_io.rb Use File.write instead of Kernel#open 2024-07-09 13:01:44 +09:00
test_jump.rb Ensure test suite is compatible with --frozen-string-literal 2024-03-14 17:56:15 +01:00
test_literal.rb Avoid array allocation for *nil, by not calling nil.to_a 2025-03-27 11:17:40 -07:00
test_literal_suffix.rb [PRISM] Enhance syntax error message extraction in test_literal_suffix btest 2024-04-03 17:34:12 -04:00
test_load.rb [Feature #21116] Extract RJIT as a third-party gem 2025-02-13 18:01:03 +09:00
test_marshal.rb
test_massign.rb
test_method.rb Fix assertion failure with anonymous splats 2025-04-02 19:31:05 -07:00
test_objectspace.rb Use a monotonically increasing number for object_id 2019-11-07 09:31:07 -08:00
test_proc.rb Make proc/Proc.new without block an error instead of warning 2020-06-10 17:49:54 -07:00
test_ractor.rb Fix crash when instantiating classes in Ractors 2025-05-09 10:24:38 -04:00
test_string.rb
test_struct.rb
test_syntax.rb [Feature #21116] Extract RJIT as a third-party gem 2025-02-13 18:01:03 +09:00
test_thread.rb [Feature #21116] Extract RJIT as a third-party gem 2025-02-13 18:01:03 +09:00
test_yjit.rb YJIT: Fix potential infinite loop when OOM (GH-13186) 2025-04-28 21:50:29 +09:00
test_yjit_30k_ifelse.rb * append newline at EOF. [ci skip] 2021-10-21 08:12:53 +09:00
test_yjit_30k_methods.rb * append newline at EOF. [ci skip] 2021-10-21 08:12:53 +09:00
test_yjit_rust_port.rb Rust YJIT 2022-04-27 11:00:22 -04:00