We ran this against Celluloid::IO master, as well as 0.15.0 and 0.14.1 and they all reliably fail on this. When an Actor links to another actor after opening a Celluloid::IO::TCPSocket, the link seems to deadlock sometimes.
Using a regular TCPSocket fixes the problem, so does making a synchronous call to another actor after opening the socket. Linking the other actor before opening the socket is an easy work-around for the bug.
We needed some thread-safe counter, so we use Atomic for that. It is reproducible without it.
It fails on JRuby 1.7.6 and 1.7.4, it seems to succeed on MRI.
require "celluloid/io"
require "atomic"
class A
include Celluloid::IO
class B
include Celluloid
def foo; end
end
def listen
# B.new_link # this works!
socket = TCPSocket.new("www.google.com", 80)
$reference.update { |x| x + 1 }
# B.new.foo # for some reason, this solves the problem too
B.new_link # this does not work!
$counter.update { |x| x + 1 }
end
end
$counter = Atomic.new(0)
$reference = Atomic.new(0)
100.times { A.new.async.listen }
puts "Wait 5 seconds."
sleep(5)
puts "Total: #{$counter.value} of #{$reference.value}"
We ran this against Celluloid::IO master, as well as 0.15.0 and 0.14.1 and they all reliably fail on this. When an Actor links to another actor after opening a
Celluloid::IO::TCPSocket
, the link seems to deadlock sometimes.Using a regular
TCPSocket
fixes the problem, so does making a synchronous call to another actor after opening the socket. Linking the other actor before opening the socket is an easy work-around for the bug.We needed some thread-safe counter, so we use Atomic for that. It is reproducible without it.
It fails on JRuby 1.7.6 and 1.7.4, it seems to succeed on MRI.
Expected output:
Actual output:
/cc @Burgestrand