@@ -523,32 +523,41 @@ def write_with_timeout(*args, timeout:)
523523
524524 def write_chunk ( chunk , timeout )
525525 deadline = Utils . monotonic_time + timeout
526+
526527 written = 0
527- begin
528- written += @socket . write_nonblock ( chunk [ written ..-1 ] )
529- rescue IO ::WaitWritable , Errno ::EINTR
530- select_timeout = deadline - Utils . monotonic_time
531- rv = Kernel . select ( nil , [ @socket ] , nil , select_timeout )
532- if BSON ::Environment . jruby?
533- # Ignore the return value of Kernel.select.
534- # On JRuby, select appears to return nil prior to timeout expiration
535- # (apparently due to a EAGAIN) which then causes us to fail the read
536- # even though we could have retried it.
537- # Check the deadline ourselves.
538- if deadline
539- select_timeout = deadline - Utils . monotonic_time
540- if select_timeout <= 0
541- raise_timeout_error! ( "Took more than #{ timeout } seconds to receive data" , true )
542- end
528+ while written < chunk . length
529+ begin
530+ written += @socket . write_nonblock ( chunk [ written ..-1 ] )
531+ rescue IO ::WaitWritable , Errno ::EINTR
532+ if !wait_for_socket_to_be_writable ( deadline )
533+ raise_timeout_error! ( "Took more than #{ timeout } seconds to receive data" , true )
543534 end
544- elsif rv . nil?
545- raise_timeout_error! ( "Took more than #{ timeout } seconds to receive data (select call timed out)" , true )
535+
536+ retry
546537 end
547- retry
548538 end
539+
549540 written
550541 end
551542
543+ def wait_for_socket_to_be_writable ( deadline )
544+ select_timeout = deadline - Utils . monotonic_time
545+ rv = Kernel . select ( nil , [ @socket ] , nil , select_timeout )
546+ if BSON ::Environment . jruby?
547+ # Ignore the return value of Kernel.select.
548+ # On JRuby, select appears to return nil prior to timeout expiration
549+ # (apparently due to a EAGAIN) which then causes us to fail the read
550+ # even though we could have retried it.
551+ # Check the deadline ourselves.
552+ select_timeout = deadline - Utils . monotonic_time
553+ return select_timeout > 0
554+ elsif rv . nil?
555+ return false
556+ end
557+
558+ true
559+ end
560+
552561 def unix_socket? ( sock )
553562 defined? ( UNIXSocket ) && sock . is_a? ( UNIXSocket )
554563 end
0 commit comments