Take the following code:
require 'socket'
require 'thread'
server = TCPServer.new("localhost", 0)
serv_thread = Thread.new{ server.accept }
sleep(0.1)
sock = TCPSocket.new("localhost", server.addr[1])
q = Queue.new
client_thread = Thread.new{
begin
sock.readline
rescue StandardError => e
q.push(e)
end
}
sleep(0.1) while client_thread.status == "run"
sock.close
# client_thread.wakeup rescue nil
err = q.pop
client_thread.join
fail "Failure!" unless err.is_a?(IOError)
puts "Success!"
So, we've got one thread blocked on a #readline, and another thread
closes the socket out from under it. On 1.8.7-p302, this completes
successfully. On 1.9.2-p136, it hangs at q.pop.
I cannot confirm this:
15:40:10 Temp$ ruby19 -v
ruby 1.9.2p136 (2010-12-25 revision 30365) [i386-cygwin]
15:40:50 Temp$ ruby19 s.rb
#<IOError: closed stream>
Success!
15:41:31 Temp$ cat s.rb
require 'socket'
require 'thread'
server = TCPServer.new("localhost", 0)
serv_thread = Thread.new{ server.accept }
sleep(0.1)
sock = TCPSocket.new("localhost", server.addr[1])
q = Queue.new
client_thread = Thread.new{
begin
sock.readline
q.push "OK"
rescue StandardError => e
p e
q.push(e)
end
}
sleep(0.1) while client_thread.status == "run"
sock.close
# client_thread.wakeup rescue nil
err = q.pop
# client_thread.join
fail "Failure!" unless err.is_a?(IOError)
puts "Success!"
15:41:36 Temp$
If I uncomment the client_thread.wakeup call, both complete (although
the rescue is necessary to prevent a ThreadError on 1.8.7).
Is this expected? Which is "correct"?
Hm... I would expect your 1.9.2 to also throw.
Btw, one thing is odd about your test case: you have two mechanisms to
synchronize threads - you read from the queue and you join
client_thread. If you really only want to track status of the thread
you could as well use Thread#value:
client_thread = Thread.new{
begin
sock.readline
nil
rescue StandardError => e
e
end
}
err = client_thread.value
Kind regards
robert
···
On Thu, Feb 10, 2011 at 12:59 PM, Alex Young <alex@blackkettle.org> wrote:
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/