Bug #21037
openRactors hang with multiple threads
Description
The following program hangs, but I don't expect it to hang:
# frozen_string_literal: true
class Map
def initialize
@r = Ractor.new {
cache = { "int" => "integer", "bool" => "boolean" }
loop do
key = receive
Ractor.yield key
end
}
freeze
end
def fetch(key)
@r.send key
m = @r.take
raise unless key == m
m
end
end
tm = Map.new
t1 = Thread.new { 10.times { |i| p [i + 1,tm.fetch("int")] } }
t2 = Thread.new { 10.times { |i| p [i + 1, tm.fetch("bool")] } }
t1.join
t2.join
I'm not sure why this program hangs yet, but it does both on macOS and Linux. I've tested with master, Ruby 3.4, and Ruby 3.3. I'm not sure why it's hanging yet, but I wanted to file an issue.
Updated by luke-gru (Luke Gruber) about 14 hours ago · Edited
Maybe this fixes it? https://github.com/ruby/ruby/pull/12520
Edit: I just tried with this branch but it seems unrelated. If you run with RUBY_DEBUG it fails an assertion having to do with ractor sleep (the receive
call). I'll take a look when I get a chance.
Updated by luke-gru (Luke Gruber) about 13 hours ago · Edited
It seems calling ractor.take
from multiple threads is unsupported at the moment. I don't know if this is a limitation or a bug. Of course, you can work around it and call select
or take
from a single thread, like main, and signal a ready event with a queue or something for the consumer threads.
Edit: There are some TODOs in the codebase having to do with waiting threads for ractors, and they explicitly say "TODO: make multithreaded". This is a known problem, at least for @ko1 (Koichi Sasada).