-
Type: Bug
-
Resolution: Fixed
-
Priority: Major - P3
-
Affects Version/s: None
-
Component/s: Connections
-
None
-
Fully Compatible
The driver does currently not set timeouts on the socket objects, instead using IO#select to perform operations with timeouts. This works for explicit reads and writes but not for the Socket#alive? call, which delegates to Socket#eof, which is implemented thusly:
299: def eof?
=> 300: fill_rbuff if !@eof && @rbuffer.empty?
301: @eof && @rbuffer.empty?
302: end
The buffer fill here is not subject to a timeout and can block indefinitely.
The driver only calls eof? after IO#select indicates the socket has readable data:
63: def alive? 64: sock_arr = [ @socket ] 65: if Kernel::select(sock_arr, nil, sock_arr, 0) => 66: eof? 67: else 68: true 69: end 70: end
However, the select call only peeks data for non-SSL connections, per its documentation:
> IO.select peeks the buffer of IO objects for testing readability. If the IO buffer is not empty, IO.select immediately notifies readability. This "peek" only happens for IO objects. It does not happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
For SSL sockets, it seems that select claims the socket is readable even when it is not and the read would block.