ml.ruby-lang.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

ruby-core

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
ruby-core@ml.ruby-lang.org

December 2025

  • 2 participants
  • 215 discussions
[ruby-core:116061] [Ruby master Bug#20158] Ractor affects Coverage results
by janosch-x 09 Sep '26

09 Sep '26
Issue #20158 has been reported by janosch-x (Janosch Müller). ---------------------------------------- Bug #20158: Ractor affects Coverage results https://bugs.ruby-lang.org/issues/20158 * Author: janosch-x (Janosch Müller) * Status: Open * Priority: Normal * ruby -v: ruby 3.3.0preview1 (2023-05-12 master a1b01e7701) [arm64-darwin22] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- I have a large rspec test suite. I found that if I call a Ractor, the Coverage results are strongly affected, i.e. almost all files appear to be uncovered. This happens even if I only ever call a Ractor before the library or rspec are required. Unfortunately, I was not able to build a simple repro yet. I assume it is a timing thing and only affects larger suites, or it only happens if there are multiple files, and maybe if the library lazily requires its sub-modules? However, I guess this should produce the same results when added to the spec_helper.rb of other large suites: ```ruby # Ractor.new { nil } # uncomment this to affect coverage results require 'coverage' Coverage.start # require library, set up rspec etc. RSpec.configuration.after(:suite) do # this number is greatly reduced and unstable when calling Ractor above p Coverage.result.values.sum { |arr| arr.sum(&:to_i) } end ``` I had this problem in [this library](https://github.com/jaynetics/character_set/). The problem affects simplecov users as well, as described [here](https://github.com/simplecov-ruby/simplecov/issues/1058). -- https://bugs.ruby-lang.org/
4 5
0 0
[ruby-core:121941] [Ruby Bug#21315] Finalizers violate the `rb_ractor_confirm_belonging` assertion
by byroot (Jean Boussier) 09 Sep '26

09 Sep '26
Issue #21315 has been reported by byroot (Jean Boussier). ---------------------------------------- Bug #21315: Finalizers violate the `rb_ractor_confirm_belonging` assertion https://bugs.ruby-lang.org/issues/21315 * Author: byroot (Jean Boussier) * Status: Open * Assignee: ractor * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- Reproduction (with assertions enabled): ```ruby require "tempfile" Ractor.new do 10.times do Tempfile.new end end.take GC.start ``` ``` <OBJ_INFO:rb_ractor_confirm_belonging@../src/ractor_core.h:375> (File) /home/runner/work/ruby/ruby/src/lib/tempfile.rb:387: [BUG] rb_ractor_confirm_belonging object-ractor id:1, current-ractor id:2 ruby 3.5.0dev (2025-05-09T15:51:24Z pull/13291/merge e289a1dc58) +PRISM [x86_64-linux] -- Control frame information ----------------------------------------------- c:0005 p:0007 s:0025 e:000024 METHOD /home/runner/work/ruby/ruby/src/lib/tempfile.rb:387 [FINISH] c:0004 p:0022 s:0020 e:000019 METHOD /home/runner/work/ruby/ruby/src/lib/prism/parse_result.rb:833 [FINISH] c:0003 p:---- s:0012 e:000011 CFUNC :parse_lex_file c:0002 p:0006 s:0007 e:000006 BLOCK /home/runner/work/ruby/ruby/src/test/prism/ractor_test.rb:26 [FINISH] c:0001 p:---- s:0003 e:000002 DUMMY [FINISH] -- Ruby level backtrace information ---------------------------------------- /home/runner/work/ruby/ruby/src/test/prism/ractor_test.rb:26:in 'block in test_parse_lex_file' /home/runner/work/ruby/ruby/src/test/prism/ractor_test.rb:26:in 'parse_lex_file' /home/runner/work/ruby/ruby/src/lib/prism/parse_result.rb:833:in 'initialize' /home/runner/work/ruby/ruby/src/lib/tempfile.rb:387:in 'call' -- Threading information --------------------------------------------------- Total ractor count: 2 Ruby thread count for this ractor: 1 -- C level backtrace information ------------------------------------------- /home/runner/work/ruby/ruby/build/ruby(rb_print_backtrace+0x14) [0x561441aeedbf] ../src/vm_dump.c:843 /home/runner/work/ruby/ruby/build/ruby(rb_vm_bugreport) ../src/vm_dump.c:1175 /home/runner/work/ruby/ruby/build/ruby(bug_report_end+0x0) [0x561441aa3f39] ../src/error.c:1097 /home/runner/work/ruby/ruby/build/ruby(rb_bug_without_die_internal) ../src/error.c:1097 /home/runner/work/ruby/ruby/build/ruby(die+0x0) [0x5614416e237f] ../src/error.c:1115 /home/runner/work/ruby/ruby/build/ruby(rb_bug) ../src/error.c:1117 /home/runner/work/ruby/ruby/build/ruby(rb_ractor_confirm_belonging+0xde) [0x56144188c6be] ../src/ractor_core.h:376 /home/runner/work/ruby/ruby/build/ruby(vm_exec_core+0xef) [0x5614418b23ef] /home/runner/work/ruby/ruby/build/vm.inc:2500 /home/runner/work/ruby/ruby/build/ruby(rb_vm_exec+0x156) [0x5614418a4676] ../src/vm.c:2618 /home/runner/work/ruby/ruby/build/ruby(vm_call0_cc+0x13d) [0x5614418aa1dd] ../src/vm_eval.c:101 /home/runner/work/ruby/ruby/build/ruby(rb_vm_call0+0x4c) [0x5614418b1cc5] ../src/vm_eval.c:61 /home/runner/work/ruby/ruby/build/ruby(rb_vm_call_kw) ../src/vm_eval.c:326 /home/runner/work/ruby/ruby/build/ruby(rb_check_funcall_default_kw) ../src/vm_eval.c:694 /home/runner/work/ruby/ruby/build/ruby(rb_gc_run_obj_finalizer+0x1cf) [0x56144170220f] ../src/gc.c:306 /home/runner/work/ruby/ruby/build/ruby(rb_multi_ractor_p+0x0) [0x56144170246f] ../src/gc/default/default.c:2820 /home/runner/work/ruby/ruby/build/ruby(rb_vm_lock_enter) ../src/vm_sync.h:74 /home/runner/work/ruby/ruby/build/ruby(rb_gc_vm_lock) ../src/gc.c:137 /home/runner/work/ruby/ruby/build/ruby(finalize_list) ../src/gc/default/default.c:2843 /home/runner/work/ruby/ruby/build/ruby(finalize_deferred_heap_pages) ../src/gc/default/default.c:2866 ``` I think it wouldn't be hard to disable that check when running a finalizer, but I don't know if it's the correct thing to do. -- https://bugs.ruby-lang.org/
5 8
0 0
[ruby-core:112091] [Ruby master Bug#19387] Issue with ObjectSpace.each_objects not returning IO objects after starting a ractor
by luke-gru (Luke Gruber) 09 Sep '26

09 Sep '26
Issue #19387 has been reported by luke-gru (Luke Gruber). ---------------------------------------- Bug #19387: Issue with ObjectSpace.each_objects not returning IO objects after starting a ractor https://bugs.ruby-lang.org/issues/19387 * Author: luke-gru (Luke Gruber) * Status: Open * Priority: Normal * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- ```ruby r = Ractor.new do receive # block, the problem is not the termination of the ractor but the starting end ObjectSpace.each_object(IO) { |io| p io # we get no objects } ``` -- https://bugs.ruby-lang.org/
6 9
0 0
[ruby-core:115328] [Ruby master Bug#19996] `RUBY_MN_THREADS=1` triggers Action Cable unit test failures
by yahonda (Yasuo Honda) 08 Sep '26

08 Sep '26
Issue #19996 has been reported by yahonda (Yasuo Honda). ---------------------------------------- Bug #19996: `RUBY_MN_THREADS=1` triggers Action Cable unit test failures https://bugs.ruby-lang.org/issues/19996 * Author: yahonda (Yasuo Honda) * Status: Open * Priority: Normal * ruby -v: ruby 3.3.0dev (2023-11-09T16:24:15Z :detached: c49adfab5d) +MN [x86_64-linux] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- ### Steps to reproduce 1. Install `ruby 3.3.0dev` 2. Set `RUBY_MN_THREADS=1` environment variable 3. git clone https://github.com/rails/rails cd rails rm Gemfile.lock bundle install cd actioncable bin/test test/channel/base_test.rb test/subscription_adapter/redis_test.rb test/channel/test_case_test.rb test/subscription_adapter/redis_test.rb test/client_test.rb --seed 14800 ``` ### Expected behavior It should pass as not setting ``` $ unset RUBY_MN_THREADS $ bin/test test/channel/base_test.rb test/subscription_adapter/redis_test.rb test/channel/test_case_test.rb test/subscription_adapter/redis_test.rb test/client_test.rb --seed 14800 /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/minitest-5.20.0/lib/minitest.rb:3: warning: mutex_m which will no longer be part of the default gems since Ruby 3.4.0. Add mutex_m to your Gemfile or gemspec. Run options: --seed 14800 # Running: ......................................................................... Finished in 12.031310s, 6.0675 runs/s, 46.7115 assertions/s. 73 runs, 562 assertions, 0 failures, 0 errors, 0 skips $ ``` ### Actual behavior It usually fails as follows. ``` $ bin/test test/channel/base_test.rb test/subscription_adapter/redis_test.rb test/channel/test_case_test.rb test/subscription_adapter/redis_test.rb test/client_test.rb --seed 14800 /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/minitest-5.20.0/lib/minitest.rb:3: warning: mutex_m which will no longer be part of the default gems since Ruby 3.4.0. Add mutex_m to your Gemfile or gemspec. Run options: --seed 14800 # Running: ..................................................F Failure: RedisAdapterTest::AlternateConfiguration#test_channel_prefix [/home/yahonda/src/github.com/rails/rails/actioncable/test/subscription_adapter/common.rb:35]: Expected #<Concurrent::Event:0x00007f0b2698d4f0 @__Lock__=#<Thread::Mutex:0x00007f0b26f8cab8>, @__Condition__=#<Thread::ConditionVariable:0x00007f0b26f8ca90>, @set=false, @iteration=0> to be set?. bin/test test/subscription_adapter/channel_prefix.rb:6 .F Failure: RedisAdapterTest::AlternateConfiguration#test_multiple_broadcast [/home/yahonda/src/github.com/rails/rails/actioncable/test/subscription_adapter/common.rb:35]: Expected #<Concurrent::Event:0x00007f0b2698a4d0 @__Lock__=#<Thread::Mutex:0x00007f0b26fac688>, @__Condition__=#<Thread::ConditionVariable:0x00007f0b26fac4f8>, @set=false, @iteration=0> to be set?. bin/test test/subscription_adapter/common.rb:74 E Error: ClientTest#test_interacting_clients: ThreadError: queue empty <internal:thread_sync>:18:in `pop' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:168:in `read_message' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:241:in `block (2 levels) in test_interacting_clients' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:218:in `block (2 levels) in concurrently' /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/promises.rb:1583:in `evaluate_to' /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/promises.rb:1766:in `block in on_resolvable' /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:352:in `run_task' /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:343:in `block (3 levels) in create_worker' <internal:kernel>:187:in `loop' /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:334:in `block (2 levels) in create_worker' /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:333:in `catch' /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:333:in `block in create_worker' /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/promises.rb:1258:in `raise' /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/promises.rb:1258:in `wait_until_resolved!' /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/promises.rb:988:in `value!' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:218:in `map' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:218:in `concurrently' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:240:in `block in test_interacting_clients' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:90:in `with_puma_server' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:234:in `test_interacting_clients' bin/test test/client_test.rb:233 E Error: ClientTest#test_disappearing_client: ThreadError: queue empty <internal:thread_sync>:18:in `pop' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:168:in `read_message' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:275:in `block in test_disappearing_client' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:90:in `with_puma_server' /home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:273:in `test_disappearing_client' bin/test test/client_test.rb:272 .................. Finished in 1323.812615s, 0.0551 runs/s, 0.3830 assertions/s. 73 runs, 507 assertions, 2 failures, 2 errors, 0 skips $ ``` -- https://bugs.ruby-lang.org/
3 2
0 0
[ruby-core:118182] [Ruby master Bug#20526] File.open(encoding: "bom|utf-8") converts "\r\n" to "\n" on Windows
by kou (Kouhei Sutou) 08 Sep '26

08 Sep '26
Issue #20526 has been reported by kou (Kouhei Sutou). ---------------------------------------- Bug #20526: File.open(encoding: "bom|utf-8") converts "\r\n" to "\n" on Windows https://bugs.ruby-lang.org/issues/20526 * Author: kou (Kouhei Sutou) * Status: Open * Target version: 3.2 * ruby -v: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x64-mingw-ucrt] * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- I'm not sure whether this is an intentional behavior but it seems that `encoding: "utf-8"` doesn't change newline conversion but `encoding: "bom|utf-8"` changes newline conversion: ```ruby File.write("a.txt", "a\r\n") File.read("a.txt").bytes # => [97, 13, 10] File.open("a.txt", encoding: "utf-8") {|f| f.read.bytes} # => [97, 10, 10] File.open("a.txt", encoding: "bom|utf-8") {|f| f.read.bytes} # => [97, 10] XXX: \r\n -> \n File.open("a.txt", encoding: "bom|utf-8", universal_newline: false) {|f| f.read.bytes} # => [97, 13, 10] ``` Note that the `XXX: ` line the above codes. Is this an intentional behavior? -- https://bugs.ruby-lang.org/
3 5
0 0
[ruby-core:120897] [Ruby master Bug#21119] Programs containing `Dir.glob` with a thread executing a CPU-heavy task run very slowly.
by genya0407 (Yusuke Sangenya) 05 Sep '26

05 Sep '26
Issue #21119 has been reported by genya0407 (Yusuke Sangenya). ---------------------------------------- Bug #21119: Programs containing `Dir.glob` with a thread executing a CPU-heavy task run very slowly. https://bugs.ruby-lang.org/issues/21119 * Author: genya0407 (Yusuke Sangenya) * Status: Open * ruby -v: ruby 3.5.0dev (2025-02-06T14:10:34Z master adbf9c5b36) +PRISM [arm64-darwin24] * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- Executing the following code in Ruby 3.4.1 takes a very long time, especially when there are many files \(100~\) in the current directory. This delay does not occur in Ruby 3.3.6. ## Reproducible script ```ruby # hoge.rb # Launch a thread to execute CPU-heavy task Thread.new do loop do arr = [] 100.times do arr << rand(1...100) end end end # Execute a program containing `Dir.glob` in the main thread. 10.times do Dir.glob('*') puts "aaaa" end ``` ## Execution Results Executiong the above code in Ruby 3.4.1 takes **119.43s**. ```shell $ ruby -v ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin24] $ time ruby hoge.rb aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa ruby hoge.rb 119.43s user 0.30s system 99% cpu 1:59.89 total ``` Executing it in Ruby master also takes **118.87s**. ```shell $ ~/opt-ruby/bin/ruby -v ruby 3.5.0dev (2025-02-06T14:10:34Z master adbf9c5b36) +PRISM [arm64-darwin24] $ time ~/opt-ruby/bin/ruby hoge.rb aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa ~/opt-ruby/bin/ruby hoge.rb 118.87s user 0.46s system 99% cpu 2:00.45 total ``` Executing it in Ruby 3.3.6 takes only **2.22s**. ```shell $ ruby -v ruby 3.3.6 (2024-11-05 revision 75015d4c1f) [arm64-darwin24] $ time ruby hoge.rb aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa ruby hoge.rb 2.22s user 0.03s system 98% cpu 2.286 total ``` So, there are roughly **50x** delays. ## Possible Cause From Ruby 3.4.0, `Dir.glob` releases the GVL frequently. * https://bugs.ruby-lang.org/issues/20587 * https://github.com/ruby/ruby/pull/11147 Due to this change, when a CPU-heavy thread releases the GVL, `Dir.glob` also releases the GVL immediately. As a result, `Dir.glob` gets significantly delayed because it has to continuously regain the GVL causing a major slowdown in execution. ## Note about Execution Results I measured the execution results under a stress condition, with 100 files in the current directory. If there are fewer files, the slowdown may be less pronounced. -- https://bugs.ruby-lang.org/
6 6
0 0
[ruby-core:116615] [Ruby master Bug#20243] M:N threading VM_ASSERT failure in rb_current_execution_context with clang 17 (on Linux)
by kjtsanaktsidis (KJ Tsanaktsidis) 31 Aug '26

31 Aug '26
Issue #20243 has been reported by kjtsanaktsidis (KJ Tsanaktsidis). ---------------------------------------- Bug #20243: M:N threading VM_ASSERT failure in rb_current_execution_context with clang 17 (on Linux) https://bugs.ruby-lang.org/issues/20243 * Author: kjtsanaktsidis (KJ Tsanaktsidis) * Status: Open * Priority: Normal * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- When building with Clang 17 and `-DVM_CHECK_MODE=1` (with the following configure) ``` optflags="-ggdb3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -O3" cflags="-DVM_CHECK_MODE=1" CC=clang ../configure --prefix=/home/kj/ruby/installed --enable-yjit=dev --disable-install-doc ``` And then running the following script with the built `./miniruby` (which is actually from `bootstraptest/test_ractor.rb`): ```ruby counts = [] counts << Ractor.count ractors = (1..3).map { Ractor.new { Ractor.receive } } counts << Ractor.count ractors[0].send('End 0').take sleep 0.1 until ractors[0].inspect =~ /terminated/ counts << Ractor.count ractors[1].send('End 1').take sleep 0.1 until ractors[1].inspect =~ /terminated/ counts << Ractor.count ractors[2].send('End 2').take sleep 0.1 until ractors[2].inspect =~ /terminated/ counts << Ractor.count counts.inspect ``` I get the following crash: ``` Assertion Failed: ../vm_core.h:1957:rb_current_execution_context:ec == rb_current_ec_noinline() ruby 3.4.0dev (2024-02-07T07:52:06Z ktsanaktsidis/igno.. 5cc6d944c2) [x86_64-linux] -- Control frame information ----------------------------------------------- c:0003 p:0003 s:0010 e:000009 METHOD <internal:ractor>:431 c:0002 p:0004 s:0006 e:000005 BLOCK ractor_crash.rb:3 [FINISH] c:0001 p:---- s:0003 e:000002 DUMMY [FINISH] -- Ruby level backtrace information ---------------------------------------- ractor_crash.rb:3:in `block (2 levels) in <main>' <internal:ractor>:431:in `receive' -- Threading information --------------------------------------------------- Total ractor count: 2 Ruby thread count for this ractor: 1 -- C level backtrace information ------------------------------------------- /home/kj/ruby/build/miniruby(rb_print_backtrace+0x14) [0x55faa97a4ebd] ../vm_dump.c:820 /home/kj/ruby/build/miniruby(rb_vm_bugreport) ../vm_dump.c:1151 /home/kj/ruby/build/miniruby(rb_assert_failure+0x81) [0x55faa94d2719] ../error.c:1131 ./miniruby(thread_sched_wait_running_turn+0x2e9) [0x55faa9726f59] /home/kj/ruby/build/miniruby(rb_ractor_sched_sleep+0x10b) [0x55faa972687b] ../thread_pthread.c:1348 /home/kj/ruby/build/miniruby(ractor_check_ints+0x0) [0x55faa968b328] ../ractor.c:683 /home/kj/ruby/build/miniruby(ractor_sleep_with_cleanup) ../ractor.c:684 /home/kj/ruby/build/miniruby(ractor_sleep+0x15) [0x55faa968adf4] ../ractor.c:701 /home/kj/ruby/build/miniruby(ractor_wait_receive) ../ractor.c:748 /home/kj/ruby/build/miniruby(ractor_receive+0x1f) [0x55faa968768e] ../ractor.c:762 /home/kj/ruby/build/miniruby(builtin_inline_class_431) ../ractor.rb:432 /home/kj/ruby/build/miniruby(builtin_invoker0+0x6) [0x55faa978fc66] ../vm_insnhelper.c:6746 /home/kj/ruby/build/miniruby(invoke_bf+0x39) [0x55faa979816e] ../vm_insnhelper.c:6886 /home/kj/ruby/build/miniruby(vm_invoke_builtin_delegate) ../vm_insnhelper.c:6909 /home/kj/ruby/build/miniruby(rb_vm_check_ints+0x0) [0x55faa9771fac] ../insns.def:1533 /home/kj/ruby/build/miniruby(vm_pop_frame) ../vm_insnhelper.c:419 /home/kj/ruby/build/miniruby(vm_exec_core) ../insns.def:1537 /home/kj/ruby/build/miniruby(vm_exec_loop+0x0) [0x55faa9767f02] ../vm.c:2489 /home/kj/ruby/build/miniruby(rb_vm_exec) ../vm.c:2492 /home/kj/ruby/build/miniruby(invoke_block+0x6f) [0x55faa9781a58] ../vm.c:1512 /home/kj/ruby/build/miniruby(invoke_iseq_block_from_c) ../vm.c:1582 /home/kj/ruby/build/miniruby(invoke_block_from_c_proc) ../vm.c:1680 /home/kj/ruby/build/miniruby(vm_invoke_proc) ../vm.c:1710 /home/kj/ruby/build/miniruby(rb_vm_invoke_proc_with_self+0x5a) [0x55faa9781eaa] ../vm.c:1745 /home/kj/ruby/build/miniruby(thread_do_start_proc+0x199) [0x55faa9739e19] ../thread.c:574 /home/kj/ruby/build/miniruby(thread_do_start+0x6c) [0x55faa973933f] ../thread.c:618 /home/kj/ruby/build/miniruby(thread_start_func_2) ../thread.c:668 /home/kj/ruby/build/miniruby(rb_native_mutex_lock+0x0) [0x55faa973a141] ../thread_pthread.c:2234 /home/kj/ruby/build/miniruby(thread_sched_lock_) ../thread_pthread.c:387 /home/kj/ruby/build/miniruby(call_thread_start_func_2) ../thread_pthread_mn.c:436 /home/kj/ruby/build/miniruby(co_start) ../thread_pthread_mn.c:434 ``` The failing assertion is this one in vm_core.h: https://github.com/ruby/ruby/blob/42c36269403baac67b0d5dc1d6d6e31168cf6a1f/…. It actually has a very helpful comment. ``` /* On the shared objects, `__tls_get_addr()` is used to access the TLS * and the address of the `ruby_current_ec` can be stored on a function * frame. However, this address can be mis-used after native thread * migration of a coroutine. * 1) Get `ptr =&ruby_current_ec` op NT1 and store it on the frame. * 2) Context switch and resume it on the NT2. * 3) `ptr` is used on NT2 but it accesses to the TLS on NT1. * This assertion checks such misusage. * * To avoid accidents, `GET_EC()` should be called once on the frame. * Note that inlining can produce the problem. */ VM_ASSERT(ec == rb_current_ec_noinline()); ``` What seems to be happening is exactly that. This is a disassembly of the relevant bits of `thread_sched_wait_running_turn`: ``` ........ # This is the only bits of the entire function which access the TLS base register %fs. # It seems to have spilled the value of ruby_current_ec into %r13. 0x000055603d2e1cf8 <+136>: mov $0xffffffffffffff90,%rax 0x000055603d2e1cff <+143>: mov %fs:0x0,%r12 0x000055603d2e1d08 <+152>: add %rax,%r12 0x000055603d2e1d0b <+155>: mov %fs:(%rax),%r13 ........ # There's a call to coroutine_transfer, so after this point we're returned to on a # different thread 0x000055603d2e1e90 <+544>: call 0x55603d7fce84 <coroutine_transfer> # But nothing ever loads the address of ruby_current_ec from %fs again (i didn't trace # exactly the data flow from %r13 at 0x000055603d2e1d0b to here, but i assume it spilled # somewhere and now got loaded back into %r15 here). In any case, that means %r15 here # contains the value of ruby_current_ec from the _old_ thread, not the current one. 0x000055603d2e1e95 <+549>: mov %rbx,0x28(%r14) 0x000055603d2e1e99 <+553>: mov (%r12),%r15 0x000055603d2e1e9d <+557>: call 0x55603d33a010 <rb_current_ec_noinline> 0x000055603d2e1ea2 <+562>: cmp %rax,%r15 => 0x000055603d2e1ea5 <+565>: jne 0x55603d2e1f3a <thread_sched_wait_running_turn+714> ........ # assertion failure code path. 0x000055603d2e1f3a <+714>: lea 0x542c0c(%rip),%rdi # 0x55603d824b4d 0x000055603d2e1f41 <+721>: lea 0x542c12(%rip),%rdx # 0x55603d824b5a 0x000055603d2e1f48 <+728>: lea 0x542c28(%rip),%rcx # 0x55603d824b77 0x000055603d2e1f4f <+735>: mov $0x7a5,%esi 0x000055603d2e1f54 <+740>: call 0x55603d08d698 <rb_assert_failure> ``` if we look at the register values from `0x000055603d2e1ea2`: ``` (rr) print/x $rax $2 = 0x55603e159ad0 (rr) print/x $r15 $3 = 0x0 ``` So the value from `%rax` which came from `ruby_current_ec_noinline` is correctly the value of `ruby_current_ec` for this thread, and `%r15` contains a stale value from a previous thread. - Now, what can we _do_ about this, is a different question :/ There's a really good stackoverflow answer about it here: https://stackoverflow.com/questions/75592038/how-to-disable-clang-expressio…, but to summarise * longstanding GCC and Clang bugs for this exist and have been marked as WONTFIX (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26461, https://github.com/llvm/llvm-project/issues/19551) * It's even worse than this EC problem - things like `errno` also might be incorrectly persisted across coroutine switches (so e.g. an inlined C library function could in theory set `errno` in another thread, for example) * C++ actually has coroutines now, so this _must_ work for those. Clang at least has fixed some TLS problems in their C++ coroutine implementation (https://github.com/llvm/llvm-project/issues/47179) Other than reimplementing all of our coroutine stuff on top of C++ coroutines, I'm not sure what else we can do. AFAICT there's no way to tell the compiler that we clobbered the `%fs` register because that's just not a thing in its model (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66631, but i assume clang is similar). Thoughts? For now I think my workaround is to disable M:N at build time when building with ASAN (or turn optimizations down). At least this isn't a problem with `Fiber` because we never move them across threads (probably for this reason in part). -- https://bugs.ruby-lang.org/
3 4
0 0
[ruby-core:120034] [Ruby master Bug#20917] redo/next in nested begin block causes wrong order of execution
by hoshiumiarata (Arata Hoshiumi) 30 Aug '26

30 Aug '26
Issue #20917 has been reported by hoshiumiarata (Arata Hoshiumi). ---------------------------------------- Bug #20917: redo/next in nested begin block causes wrong order of execution https://bugs.ruby-lang.org/issues/20917 * Author: hoshiumiarata (Arata Hoshiumi) * Status: Open * ruby -v: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [x86_64-darwin24] * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- It seems that `redo`/`next` in a nested `begin` block can cause the wrong order of execution. For example: ```ruby for _ in [0] puts 0 begin puts 1 begin puts 2 redo ensure puts 3 end ensure puts 4 break end end ``` It prints: ``` 0 1 2 3 4 3 4 => nil ``` But I think it should print: ``` 0 1 2 3 4 => nil ``` Because execution order should be: 1. `puts 0` 2. `puts 1` 3. `puts 2` 4. `redo` 5. unwind to nested `ensure` block 6. `puts 3` 7. unwind to outer `ensure` block 8. `puts 4` 9. `break` 10. end of loop Interestingly enough, if we add an empty `rescue` block before any of the `ensure` blocks, then the execution order is correct. -- https://bugs.ruby-lang.org/
4 3
0 0
[ruby-core:114645] [Ruby master Bug#19865] Segfault when calling user signal handlers during VM shutdown
by ivoanjo (Ivo Anjo) 27 Aug '26

27 Aug '26
Issue #19865 has been reported by ivoanjo (Ivo Anjo). ---------------------------------------- Bug #19865: Segfault when calling user signal handlers during VM shutdown https://bugs.ruby-lang.org/issues/19865 * Author: ivoanjo (Ivo Anjo) * Status: Open * Priority: Normal * ruby -v: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- Howdy 👋! I work for Datadog [on the `ddtrace` gem](https://github.com/DataDog/dd-trace-rb) . I've found this issue while investigating a [customer crash report](https://github.com/DataDog/dd-trace-rb/issues/2980). ### Background The original issue was found in a production app. A number of things need to be in play to cause it. The [`ruby-odbc`](https://rubygems.org/gems/ruby-odbc) gem provides a way of accessing databases through the ODBC API. It wraps a database connection as a Data object, with a free function that, prior to freeing the native resources, disconnects from the database if the connection was still active. Because disconnecting from the database is a blocking operation, the gem (reasonably, in my opinion), releases the global VM lock before disconnecting. The trigger for the crash is: 1. The app in question used puma, and puma installs a `Signal.trap('TERM')` 2. The database object was still connected when the app started to shut down 3. A VM shutdown starts... 4. Half-way through shutdown, the VM received a SIGTERM signal, and queued it for processing 5. The VM calls the free function on all objects 6. The ruby-odbc gem sees there's an active database connection, and tries to release the GVL to call the blocking disconnect 7. Before releasing the GVL, the VM checks for pending interruptions 8. The VM tries to run the Ruby-level signal handler method half-way through VM shutdown, when you can no longer run Ruby code 9. Segfault ### How to reproduce (Ruby version & script) I was able to reproduce on a minimal example on Ruby 3.2.2 (`ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]`) and recent master (`ruby 3.3.0dev (2023-08-17T07:30:01Z master d26b015e83) [x86_64-linux]`). I've put the test-case up on github as well <https://github.com/DataDog/signal-bug-testcase>, but here's the important bits: `signal-bug-testcase.rb`: ```ruby require 'signal_bug_testcase' Signal.trap("TERM") { puts "Hello, world" } FOO = SignalBugTestcase.new ``` `signal_bug_testcase.c`: ```ruby #include <ruby.h> #include <ruby/thread.h> #include <signal.h> #include <unistd.h> typedef struct { int dummy; } BugTestcase; void *test_nogvl(void *unused) { fprintf(stderr, "GVL released!\n"); return NULL; } static void bug_testcase_free(void* ptr) { fprintf(stderr, "Free getting called! Sending signal...\n"); kill(getpid(), SIGTERM); fprintf(stderr, "SIGTERM signal queued, trying to release GVL...\n"); rb_thread_call_without_gvl(test_nogvl, NULL, NULL, NULL); fprintf(stderr, "After releasing GVL!\n"); free(ptr); } const rb_data_type_t bug_testcase_data_type = { .wrap_struct_name = "SignalBugTestcase", .function = { NULL, bug_testcase_free, NULL }, .flags = RUBY_TYPED_FREE_IMMEDIATELY }; VALUE bug_testcase_alloc(VALUE klass) { BugTestcase* obj = calloc(1, sizeof(BugTestcase)); return TypedData_Make_Struct(klass, BugTestcase, &bug_testcase_data_type, obj); } void Init_signal_bug_testcase(void) { VALUE cBugTestcase = rb_define_class("SignalBugTestcase", rb_cObject); rb_define_alloc_func(cBugTestcase, bug_testcase_alloc); } ``` ### Expectation and result No segfault happens. Interestingly, on Ruby 2.7, the VM exits half-way through but doesn't always segfault, but running it a few times always triggers the issue. On 3.2+ it crashes every time for me. I suspect the right thing here is to no longer accept/try to run any Ruby-level signal handlers after VM shutdown starts. Here's what I see with this test-case: ``` $ bundle exec ruby lib/signal-bug-testcase.rb Free getting called! Sending signal... SIGTERM signal queued, trying to release GVL... lib/signal-bug-testcase.rb:3: [BUG] Segmentation fault at 0x0000000000000007 ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux] -- Control frame information ----------------------------------------------- c:0003 p:---- s:0011 e:000010 CFUNC :puts c:0002 p:0005 s:0006 e:000005 BLOCK lib/signal-bug-testcase.rb:3 [FINISH] c:0001 p:0000 s:0003 E:0001a0 DUMMY [FINISH] -- Ruby level backtrace information ---------------------------------------- lib/signal-bug-testcase.rb:3:in `block in <main>' lib/signal-bug-testcase.rb:3:in `puts' -- Machine register context ------------------------------------------------ RIP: 0x000070aa64cedbe7 RBP: 0x000070aa648e8fd0 RSP: 0x00007ffc5c057608 RAX: 0x0000000000004171 RBX: 0x00007ffc5c057630 RCX: 0x0000000000000001 RDX: 0x00007ffc5c057630 RDI: 0x0000000000000007 RSI: 0x0000000000004171 R8: 0x000000000000021b R9: 0x0000000000000000 R10: 0x000070aa63eff048 R11: 0x0000000000000000 R12: 0x000070aa648e8fd0 R13: 0x0000000000004171 R14: 0x0000000000000007 R15: 0x000070aa648e8ff0 EFL: 0x0000000000010202 -- C level backtrace information ------------------------------------------- ruby-3.2.2/lib/libruby.so.3.2(rb_print_backtrace+0xd) [0x70aa64d5bb5f] ruby-3.2.2/vm_dump.c:785 ruby-3.2.2/lib/libruby.so.3.2(rb_vm_bugreport) ruby-3.2.2/vm_dump.c:1080 ruby-3.2.2/lib/libruby.so.3.2(rb_bug_for_fatal_signal+0xf4) [0x70aa64b52164] ruby-3.2.2/error.c:813 ruby-3.2.2/lib/libruby.so.3.2(sigsegv+0x4d) [0x70aa64cab0fd] ruby-3.2.2/signal.c:964 /lib/x86_64-linux-gnu/libc.so.6(0x70aa64642520) [0x70aa64642520] ruby-3.2.2/lib/libruby.so.3.2(hash_table_index+0x0) [0x70aa64cedbe7] ruby-3.2.2/symbol.h:72 ruby-3.2.2/lib/libruby.so.3.2(rb_id_table_lookup) ruby-3.2.2/id_table.c:230 ruby-3.2.2/lib/libruby.so.3.2(cached_callable_method_entry+0x24) [0x70aa64d356bb] ruby-3.2.2/vm_method.c:1295 ruby-3.2.2/lib/libruby.so.3.2(callable_method_entry_or_negative) ruby-3.2.2/vm_method.c:1365 ruby-3.2.2/lib/libruby.so.3.2(callable_method_entry) ruby-3.2.2/vm_method.c:1402 ruby-3.2.2/lib/libruby.so.3.2(rb_callable_method_entry) ruby-3.2.2/vm_method.c:1409 ruby-3.2.2/lib/libruby.so.3.2(gccct_method_search_slowpath+0x38) [0x70aa64d36258] ruby-3.2.2/vm_eval.c:434 ruby-3.2.2/lib/libruby.so.3.2(rb_call0+0x267) [0x70aa64d4e877] ruby-3.2.2/vm_eval.c:483 ruby-3.2.2/lib/libruby.so.3.2(rb_call+0x32) [0x70aa64d4f406] ruby-3.2.2/vm_eval.c:877 ruby-3.2.2/lib/libruby.so.3.2(rb_funcallv_kw) ruby-3.2.2/vm_eval.c:1074 ruby-3.2.2/lib/libruby.so.3.2(vm_call_cfunc_with_frame+0x127) [0x70aa64d30277] ruby-3.2.2/vm_insnhelper.c:3268 ruby-3.2.2/lib/libruby.so.3.2(vm_sendish+0x97) [0x70aa64d407a4] ruby-3.2.2/vm_insnhelper.c:5080 ruby-3.2.2/lib/libruby.so.3.2(vm_exec_core) ruby-3.2.2/insns.def:820 ruby-3.2.2/lib/libruby.so.3.2(rb_vm_exec+0xd3) [0x70aa64d460d3] ruby-3.2.2/vm.c:2374 ruby-3.2.2/lib/libruby.so.3.2(rb_vm_invoke_proc+0x5f) [0x70aa64d4bfcf] ruby-3.2.2/vm.c:1603 ruby-3.2.2/lib/libruby.so.3.2(vm_call0_body+0x5df) [0x70aa64d4c5cf] ruby-3.2.2/vm_eval.c:274 ruby-3.2.2/lib/libruby.so.3.2(vm_call0_cc+0x77) [0x70aa64d4e7e7] ruby-3.2.2/vm_eval.c:87 ruby-3.2.2/lib/libruby.so.3.2(rb_call0) ruby-3.2.2/vm_eval.c:551 ruby-3.2.2/lib/libruby.so.3.2(rb_call+0x32) [0x70aa64d4f406] ruby-3.2.2/vm_eval.c:877 ruby-3.2.2/lib/libruby.so.3.2(rb_funcallv_kw) ruby-3.2.2/vm_eval.c:1074 ruby-3.2.2/lib/libruby.so.3.2(rb_eval_cmd_kw+0x142) [0x70aa64d4f562] ruby-3.2.2/vm_eval.c:1923 ruby-3.2.2/lib/libruby.so.3.2(signal_exec+0xf6) [0x70aa64caae16] ruby-3.2.2/signal.c:1064 ruby-3.2.2/lib/libruby.so.3.2(rb_threadptr_execute_interrupts+0x36b) [0x70aa64cf7078] ruby-3.2.2/thread.c:2334 ruby-3.2.2/lib/libruby.so.3.2(rb_threadptr_execute_interrupts) ruby-3.2.2/thread.c:2291 ruby-3.2.2/lib/libruby.so.3.2(rb_vm_check_ints+0xb) [0x70aa64cf7ac5] ruby-3.2.2/vm_core.h:1994 ruby-3.2.2/lib/libruby.so.3.2(rb_vm_check_ints) ruby-3.2.2/vm_core.h:1985 ruby-3.2.2/lib/libruby.so.3.2(unblock_function_set) ruby-3.2.2/thread.c:320 ruby-3.2.2/lib/libruby.so.3.2(blocking_region_begin) ruby-3.2.2/thread.c:1485 ruby-3.2.2/lib/libruby.so.3.2(rb_nogvl+0xbf) [0x70aa64cf90cf] ruby-3.2.2/thread.c:1548 signal-bug-testcase-2/lib/signal_bug_testcase.so(fprintf+0x0) [0x70aa6518f299] ../../../../ext/signal_bug_testcase/signal_bug_testcase.c:17 signal-bug-testcase-2/lib/signal_bug_testcase.so(bug_testcase_free) ../../../../ext/signal_bug_testcase/signal_bug_testcase.c:18 ruby-3.2.2/lib/libruby.so.3.2(run_final+0xf) [0x70aa64b73172] ruby-3.2.2/gc.c:4388 ruby-3.2.2/lib/libruby.so.3.2(finalize_list) ruby-3.2.2/gc.c:4407 ruby-3.2.2/lib/libruby.so.3.2(finalize_deferred_heap_pages) ruby-3.2.2/gc.c:4436 ruby-3.2.2/lib/libruby.so.3.2(rb_objspace_call_finalizer+0x350) [0x70aa64b80d70] ruby-3.2.2/gc.c:4573 ruby-3.2.2/lib/libruby.so.3.2(rb_ec_finalize+0x2a) [0x70aa64b5d6d1] ruby-3.2.2/eval.c:168 ruby-3.2.2/lib/libruby.so.3.2(rb_ec_cleanup) ruby-3.2.2/eval.c:262 ruby-3.2.2/lib/libruby.so.3.2(ruby_run_node+0x9d) [0x70aa64b5d91d] ruby-3.2.2/eval.c:330 ruby-3.2.2/bin/ruby(rb_main+0x21) [0x5d5d1295f187] ./main.c:38 ruby-3.2.2/bin/ruby(main) ./main.c:57 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_call_main+0x80) [0x70aa64629d90] ../sysdeps/nptl/libc_start_call_main.h:58 /lib/x86_64-linux-gnu/libc.so.6(call_init+0x0) [0x70aa64629e40] ../csu/libc-start.c:392 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main_impl) ../csu/libc-start.c:379 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main) (null):0 [0x5d5d1295f1d5] ``` ---Files-------------------------------- signal-bug-testcase-main.zip (7.73 KB) -- https://bugs.ruby-lang.org/
3 4
0 0
[ruby-core:115143] [Ruby master Bug#19970] Eval leaks callcache and callinfo objects on arm32 (linux)
by larsin (Lars Ingjer) 24 Aug '26

24 Aug '26
Issue #19970 has been reported by larsin (Lars Ingjer). ---------------------------------------- Bug #19970: Eval leaks callcache and callinfo objects on arm32 (linux) https://bugs.ruby-lang.org/issues/19970 * Author: larsin (Lars Ingjer) * Status: Open * Priority: Normal * ruby -v: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [armv7l-linux-eabihf] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- The following script demonstrates a memory leak on arm 32 (linux): ``` ruby def gcdiff(n) GC.start if @last_gc_stat puts "GC.stat #{n} diff old_objects: #{GC.stat(:old_objects) - @last_gc_stat}" end @last_gc_stat = GC.stat(:old_objects) end def foo end 10.times do |i| 10_000.times do eval 'foo' end gcdiff(i) puts "Number of live objects: #{GC.stat(:heap_live_slots)}" puts "Memory usage: #{`ps -o rss= -p #{$$}`}" puts end ``` Output: ``` Number of live objects: 41303 Memory usage: 11900 GC.stat 1 diff old_objects: 20037 Number of live objects: 61317 Memory usage: 13604 GC.stat 2 diff old_objects: 20001 Number of live objects: 81317 Memory usage: 14880 GC.stat 3 diff old_objects: 20000 Number of live objects: 101317 Memory usage: 16596 GC.stat 4 diff old_objects: 20000 Number of live objects: 121317 Memory usage: 17248 GC.stat 5 diff old_objects: 20000 Number of live objects: 141317 Memory usage: 18760 GC.stat 6 diff old_objects: 20000 Number of live objects: 161317 Memory usage: 19540 GC.stat 7 diff old_objects: 20000 Number of live objects: 181317 Memory usage: 21752 GC.stat 8 diff old_objects: 20000 Number of live objects: 201317 Memory usage: 21828 GC.stat 9 diff old_objects: 20000 Number of live objects: 221317 Memory usage: 24896 ``` ObjectSpace.count_imemo_objects shows that imemo_callcache and imemo_callinfo are leaking. The issue does not occur on arm64 mac or x86_64 linux with the same ruby version. The issue has also been reproduced with the latest 3.2.2 snapshot (2023-09-30). -- https://bugs.ruby-lang.org/
3 3
0 0
  • ← Newer
  • 1
  • 2
  • 3
  • 4
  • 5
  • ...
  • 22
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.