diff options
author | Alan Wu <XrXr@users.noreply.github.com> | 2022-03-28 17:00:45 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-28 17:00:45 -0400 |
commit | 51e98eab1f2d43f3d77f6e148b2bd07709379b8f (patch) | |
tree | 05ed055df63b54a9215942cb33c1ea7ae960e1a4 /ractor.c | |
parent | 5525e47a0b5e6b6c3e13ceec4b44535feba22631 (diff) |
Fix Ractor.receive_if + rb_vm_barrier() deadlock
I have this scripts that deadlocks after about
5 minutes if I repeatedly run it with a shell loop:
```ruby
$VERBOSE = nil
lamb = ->(main, gc) do
gc.verify_internal_consistency
gc.verify_internal_consistency
main << 1
gc.verify_internal_consistency
gc.verify_internal_consistency
main << 2
gc.verify_internal_consistency
gc.verify_internal_consistency
main << 3
gc.verify_internal_consistency
gc.verify_internal_consistency
end
lamb[[], GC]
lamb[[], GC]
r = Ractor.new Ractor.current, GC, &lamb
a = []
a << Ractor.receive_if{|msg| msg == 2}
a << Ractor.receive_if{|msg| msg == 3}
a << Ractor.receive_if{|msg| msg == 1}
```
Shell loop:
```shell
while ./miniruby deadlock.rb; do date; done
```
Once it locks up, CTRL-C doesn't interrupt the process which
led me to infer `receive_if` is looping in `ractor_receive_if()`
without checking for interrupts. This can be confirmed by
attaching a debugger to the deadlocked miniruby.
The deadlock has one thread looping in `receive_if`
and another waiting in `rb_vm_barrier()`. The barrier relies
on interrupt checking to finish. Theoretically speaking the
`rb_vm_barrier()` could come from one thread naturally starting GC.
We found this while developing YJIT but it dead locks running
with YJIT disabled. YJIT currently relies on `rb_vm_barrier()`
to synchronize before changing memory protection.
This diff adds an interrupt check in the loop in `Ractor#receive_if`
which seems to fix the deadlock.
In addition, this commit allows interrupting the following single
ractor script with CTRL-C.
```shell
ruby -e 'Ractor.current.send(3); Ractor.receive_if { false }'
```
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/5699
Merged-By: XrXr
Diffstat (limited to 'ractor.c')
-rw-r--r-- | ractor.c | 2 |
1 files changed, 2 insertions, 0 deletions
@@ -886,6 +886,8 @@ ractor_receive_if(rb_execution_context_t *ec, VALUE crv, VALUE b) if (result != Qundef) return result; index++; } + + RUBY_VM_CHECK_INTS(ec); } } |