Uploaded image for project: 'Ruby Driver'
  1. Ruby Driver
  2. RUBY-2140

Socket liveness checks do not time out

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 2.12.0.rc0
    • 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.

            Assignee:
            oleg.pudeyev@mongodb.com Oleg Pudeyev (Inactive)
            Reporter:
            oleg.pudeyev@mongodb.com Oleg Pudeyev (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: