diff --git a/ext/openssl/lib/openssl/ssl-internal.rb b/ext/openssl/lib/openssl/ssl-internal.rb index 356d4e8..89a7a42 100644 --- a/ext/openssl/lib/openssl/ssl-internal.rb +++ b/ext/openssl/lib/openssl/ssl-internal.rb @@ -169,7 +169,15 @@ module OpenSSL begin ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx) ssl.sync_close = true - ssl.accept if @start_immediately + if @start_immediately + # Retry on EAGAIN (may be due to underlying inprogress for TLS handshake or renegotiation requested.) + # Any other error is rescued further. + begin + ssl.accept + rescue Errno::EAGAIN + retry + end + end ssl rescue SSLError => ex sock.close diff --git a/lib/net/http.rb b/lib/net/http.rb index 9e4fe6a..41a9c75 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -797,7 +797,14 @@ module Net #:nodoc: end # Server Name Indication (SNI) RFC 3546 s.hostname = @address if s.respond_to? :hostname= - timeout(@open_timeout) { s.connect } + timeout(@open_timeout) { + # Retry on EAGAIN (may be due to underlying inprogress for TLS handshake or renegotiation requested.) + begin + s.connect + rescue Errno::EAGAIN + retry + end + } if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE s.post_connection_check(@address) end diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb index f374466..b6f9f17 100644 --- a/lib/net/protocol.rb +++ b/lib/net/protocol.rb @@ -153,6 +153,12 @@ module Net # :nodoc: else raise Timeout::Error end + rescue Errno::EAGAIN + # read_nonblock calls underlying SSL_read. openssl doc states that data can be processed only when SSL/TLS + # record has been received completely. Also data that was not retrieved at the last call of SSL_read() + # can still be buffered inside the SSL layer and will be retrieved on the next call to SSL_read. + # http://www.openssl.org/docs/ssl/SSL_read.html + retry end end