Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenSSL::SSL::SSLSocket + IO::select hangs sometimes #2195

Closed
jordansissel opened this issue Nov 14, 2014 · 3 comments
Closed

OpenSSL::SSL::SSLSocket + IO::select hangs sometimes #2195

jordansissel opened this issue Nov 14, 2014 · 3 comments

Comments

@jordansissel
Copy link
Contributor

Under MRI, the following code will result in fetching https://www.google.com/. The last two lines are "0" and blank (chunked transfer encoding over http).

However, under JRuby (tested JRuby 1.7.16.1 and 1.7.9), this hangs.

Under MRI, it successfully reads the full HTTP request and the last line output (bytes read) is 52460. However, under JRuby, it hangs in IO::select after about the 30th iteration, but is nondeterministic in behavior (though the nondeterminism may be due to Google's webservers varying its responses and variations in TCP timing).

Jruby last output example:

29: 39149
30: 40542
31: 41935

In general, JRuby gets about 30 or 31 iterations (IO::select + sysread), and around 38kb-40kb of data before the next IO::select blocks forever.

If I change the timeout in IO::select to be 1 second instead of nil, the IO::select will time out after 1 second AND the next sysread() will give me data.

Full code:

require "socket"
require "openssl"

s = TCPSocket.new("www.google.com", 443)
o = OpenSSL::SSL::SSLSocket.new(s)
o.connect

o.write("GET / HTTP/1.1\r\n")
o.write("Host: www.google.com\r\n")
o.write("\r\n")
o.flush()

bytes = 0
count = 0
data = ""
while true
  count += 1
  r, w, e = IO.select([o], nil, nil, nil)
  data <<  o.sysread(16384)
  puts "#{count}: #{data.bytesize}"
  # Chunked encoding break
  break if data =~ /0\r\n\r\n$/m
end
@rtyler rtyler added the openssl label Jan 15, 2015
@driskell
Copy link

driskell commented May 5, 2015

@jordansissel Hello! This is fairly old but I was researching non-blocking.
I think in your test though it is likely wanting to write due to a key exchange, which can sometimes happen in the middle of a read. So you should IO.select([o], [o], nil, nil) just to be sure.

@jordansissel
Copy link
Contributor Author

@driskell yeah I remember that being necessary when using OpenSSL from C, but in C we're doing select on the fd, not the openssl object as we are in Ruby, so I"m not sure - you might be totally right! :P

It's been a while, so my memory is fuzzy. I'll revisit this soon :P

@kares
Copy link
Member

kares commented Jun 22, 2018

IO.select([o], [o], nil, nil) like a charm and original select also completes after a while

@kares kares closed this as completed Jun 22, 2018
@kares kares added this to the Invalid or Duplicate milestone Jun 22, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants