[ruby-core:121093] [Ruby master Bug#21146] VM_ASSERT(expr) gives bad bug report results when another ractor fails an assertion during printing of report

Issue #21146 has been reported by luke-gru (Luke Gruber). ---------------------------------------- Bug #21146: VM_ASSERT(expr) gives bad bug report results when another ractor fails an assertion during printing of report https://bugs.ruby-lang.org/issues/21146 * Author: luke-gru (Luke Gruber) * Status: Open * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- test.rb: ```ruby rs = 100.times.map do Ractor.new do cnt = rand 3 cnt += 1 if cnt.zero? sleep cnt 100.times do |i| if i != 0 && i % 50 == 0 Ractor.fail_assert end end end end ``` ractor.rb: ```ruby def self.fail_assert __builtin_cexpr! %q{ VM_ASSERT(0), Qfalse } end ```
make run
I would like to be able to see the bug report for the first failed assertion, without any output from the other ractors. -- https://bugs.ruby-lang.org/

Issue #21146 has been updated by luke-gru (Luke Gruber). PR here: https://github.com/ruby/ruby/pull/12770 ---------------------------------------- Bug #21146: VM_ASSERT(expr) gives bad bug report results when another ractor fails an assertion during printing of report https://bugs.ruby-lang.org/issues/21146#change-112013 * Author: luke-gru (Luke Gruber) * Status: Open * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- test.rb: ```ruby rs = 100.times.map do Ractor.new do cnt = rand 3 cnt += 1 if cnt.zero? sleep cnt 100.times do |i| if i != 0 && i % 50 == 0 Ractor.fail_assert end end end end ``` ractor.rb: ```ruby def self.fail_assert __builtin_cexpr! %q{ VM_ASSERT(0), Qfalse } end ```
make run
I would like to be able to see the bug report for the first failed assertion, without any output from the other ractors. -- https://bugs.ruby-lang.org/

Issue #21146 has been updated by ko1 (Koichi Sasada). Your patch uses `RB_VM_LOCK_ENTER_NO_BARRIER` but it should block normal use of `rb_bug()` (using `rb_bug()` is irregular case though). So I think it should use simpler mechanism to synchronize `rb_bug()` calling. For example, introducing a global variable to avoid multiple `rb_bug()` calls. (btw `VM_ASSERT()` calls `rb_bug()` if `RUBY_DEBUG` (or other macros) is defined, so `rb_bug()` is suitable for the example) ---------------------------------------- Bug #21146: VM_ASSERT(expr) gives bad bug report results when another ractor fails an assertion during printing of report https://bugs.ruby-lang.org/issues/21146#change-112252 * Author: luke-gru (Luke Gruber) * Status: Open * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- test.rb: ```ruby rs = 100.times.map do Ractor.new do cnt = rand 3 cnt += 1 if cnt.zero? sleep cnt 100.times do |i| if i != 0 && i % 50 == 0 Ractor.fail_assert end end end end ``` ractor.rb: ```ruby def self.fail_assert __builtin_cexpr! %q{ VM_ASSERT(0), Qfalse } end ```
make run
I would like to be able to see the bug report for the first failed assertion, without any output from the other ractors. -- https://bugs.ruby-lang.org/

Issue #21146 has been updated by luke-gru (Luke Gruber). Thanks for your comment. I can make it simpler, but I am a bit confused as to what I should do instead. If the first thread gets to the global variable first and enters `rb_vm_bugreport`, then other threads that also try to enter this function should be blocked, but there are only a few ways to block them: 1) use a mutex, like the VM lock in my patch 2) use a blocking system call like sleep (which is also safe in a signal handler in case someone uses `VM_ASSERT` or `rb_bug` in a signal handler 3) busy-wait until the process ends, which is going to be soon anyway Would you prefer #2? Also when you say use a global variable, do you mean an atomic global? Because if not, a write could be made that goes to the CPU's write buffer and is not flushed, so two or more threads could enter the critical section at once. I'm open to doing whatever you want, because maybe I'm overthinking it for just a debug case anyway. Thanks again! ---------------------------------------- Bug #21146: VM_ASSERT(expr) gives bad bug report results when another ractor fails an assertion during printing of report https://bugs.ruby-lang.org/issues/21146#change-112263 * Author: luke-gru (Luke Gruber) * Status: Open * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- test.rb: ```ruby rs = 100.times.map do Ractor.new do cnt = rand 3 cnt += 1 if cnt.zero? sleep cnt 100.times do |i| if i != 0 && i % 50 == 0 Ractor.fail_assert end end end end ``` ractor.rb: ```ruby def self.fail_assert __builtin_cexpr! %q{ VM_ASSERT(0), Qfalse } end ```
make run
I would like to be able to see the bug report for the first failed assertion, without any output from the other ractors. -- https://bugs.ruby-lang.org/
participants (2)
-
ko1 (Koichi Sasada)
-
luke-gru (Luke Gruber)