Actions
Bug #21610
closedUse ec->interrupt_mask to prevent interrupts.
Description
The following program can trigger rb_bug
in rb_fiber_scheduler_unblock
:
require 'async/scheduler'
scheduler = Async::Scheduler.new
Fiber.set_scheduler(scheduler)
Signal.trap(:USR1) do
end
q = Thread::Queue.new
Thread.new do
loop do
Ractor.new do
Process.kill(:USR1, $$)
end.join
end
end
Fiber.schedule do
Fiber.schedule do
1.upto(1000000) do |i|
sleep 0.01
q.pop
q.push(1)
puts "1 iter push/pop"
end
end
Fiber.schedule do
1.upto(1000000) do |i|
sleep 0.01
q.push(i)
q.pop
puts "1 iter push/pop#2"
end
end
Fiber.schedule do
gets
exit!
end
end
In brief, when rb_fiber_scheduler_unblock
executes with ec->interrupt_flag
set, the following sequence can occur:
Thread A (Signaling) Thread B (Blocked Fiber)
-------------------- ---------------------
calls unblock(fiber_x)
├─ enters scheduler user code fiber_x sleeping in scheduler.block()
├─ ⚠️ SIGNAL INTERRUPT ⚠️
├─ raises SignalException
├─ unblock operation aborted
├─ scheduler state inconsistent
└─ returns believing success └─ fiber_x waits forever ⚠️
Confirmed fix: https://github.com/ruby/ruby/pull/14588
Actions
Like0
Like0Like0Like0Like0