I have a very simple socket app:
# Server
server = TCPServer.new(2000)
loop do
client = server.accept
sleep 10
end
# Client
s = TCPSocket.new('localhost', 2000)
th1 = Thread.new do
begin
Kernel.select([s], nil, [s], nil)
puts 'Select returned'
rescue => e
puts "Select raised #{e}"
end
end
th2 = Thread.new do
sleep 0.5
s.close
end
[th1, th2].map(&:join)
Now, what I want to happen is, if while the client is hanging waiting for the server to respond, the client's socket is closed by a different thread, the Kernel#select call should exit immediately and raise an error. This is what happens on MacOs, however on Linux, the call to select hangs indefinitely (or until the timeout is hit).
- Is there any way to get around this?
- I think the system call I need is poll(2), but that doesn't seem to be available in ruby?
Any help would be appreciated!
Instead of trying to interrupt the waiting thread by closing the local socket, include the read end of a pipe among the IO objects it is
selecting on. Then another thread can interrupt theselection by writing to or closing the write end of the pipe. That has the added advantage that it allows the client to distinguish between a local termination request and a remote disconnection.Something along these lines, for example: