From 0b00f74c718c6b9cdb06bd058c19689a53063a9c Mon Sep 17 00:00:00 2001 From: StabbyCutyou Date: Fri, 29 May 2015 00:21:14 -0400 Subject: [PATCH] Fixing error handling for socket timeouts that occur due to a race-like condition --- lib/poseidon/connection.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/poseidon/connection.rb b/lib/poseidon/connection.rb index a2d81f6..e1b589e 100644 --- a/lib/poseidon/connection.rb +++ b/lib/poseidon/connection.rb @@ -118,13 +118,15 @@ def read_response(response_class) s = ensure_read_or_timeout(n) buffer = Protocol::ResponseBuffer.new(s) response_class.read(buffer) - rescue Errno::ECONNRESET, SocketError, TimeoutException + rescue Errno::ECONNRESET, SocketError, Errno::ETIMEDOUT, TimeoutException @socket = nil raise_connection_failed_error end def ensure_read_or_timeout(maxlen) if IO.select([@socket], nil, nil, @socket_timeout_ms / 1000.0) + # There is a potential race condition here, where the socket could time out between IO Select and Write + # This will throw a Errno::ETIMEDOUT, but it will be caught in the calling code @socket.read(maxlen) else raise TimeoutException.new @@ -135,13 +137,15 @@ def send_request(request) buffer = Protocol::RequestBuffer.new request.write(buffer) ensure_write_or_timeout([buffer.to_s.bytesize].pack("N") + buffer.to_s) - rescue Errno::EPIPE, Errno::ECONNRESET, TimeoutException + rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ETIMEDOUT, TimeoutException @socket = nil raise_connection_failed_error end def ensure_write_or_timeout(data) if IO.select(nil, [@socket], nil, @socket_timeout_ms / 1000.0) + # There is a potential race condition here, where the socket could time out between IO Select and Write + # This will throw a Errno::ETIMEDOUT, but it will be caught in the calling code @socket.write(data) else raise TimeoutException.new