JRuby (please use github issues at http://bugs.jruby.org)
  1. JRuby (please use github issues at http://bugs.jruby.org)
  2. JRUBY-6346

Error establishing SSL connections: OpenSSL::SSL::SSLError: Socket closed

    Details

    • Type: Bug Bug
    • Status: Resolved Resolved
    • Priority: Critical Critical
    • Resolution: Not A Bug
    • Affects Version/s: JRuby 1.6.5
    • Fix Version/s: JRuby 1.7.1
    • Component/s: OpenSSL
    • Labels:
      None
    • Environment:
      Mac OSX Lion, jruby 1.6.5.1, jruby-openssl 0.7.5.dev
    • Number of attachments :
      1

      Description

      I have been intermittently seeing "SSLError: Socket closed" upon `connect`, trying to establish an SSL socket connection. Hard to tell whether it was just my connection or not. Then I noticed that it happens without fail upon `accept` when running WEBrick in https mode--except from Safari. I mean, Webrick starts up okay, but when I navigate to https://localhost:3000 in my browser (though, strangely, Safari works fine), it fails with the following backtrace:

      #<OpenSSL::SSL::SSLError: Socket closed>
      org/jruby/ext/openssl/SSLSocket.java:227:in `accept'
      /Users/mhauck/.rvm/gems/jruby-1.6.5.1/gems/jruby-openssl-0.7.5.1.dev.ibm/lib/1.9/openssl/ssl-internal.rb:164:in `accept'
      /Users/mhauck/.rvm/rubies/jruby-1.6.5.1/lib/ruby/1.9/webrick/server.rb:159:in `accept_client'
      /Users/mhauck/.rvm/rubies/jruby-1.6.5.1/lib/ruby/1.9/webrick/server.rb:94:in `start'
      org/jruby/RubyArray.java:1612:in `each'
      /Users/mhauck/.rvm/rubies/jruby-1.6.5.1/lib/ruby/1.9/webrick/server.rb:91:in `start'
      /Users/mhauck/.rvm/rubies/jruby-1.6.5.1/lib/ruby/1.9/webrick/server.rb:22:in `start'
      /Users/mhauck/.rvm/rubies/jruby-1.6.5.1/lib/ruby/1.9/webrick/server.rb:81:in `start'
      /Users/mhauck/.rvm/gems/jruby-1.6.5.1/gems/rack-1.2.4/lib/rack/handler/webrick.rb:13:in `run'
      /Users/mhauck/.rvm/gems/jruby-1.6.5.1/gems/rack-1.2.4/lib/rack/server.rb:217:in `start'
      /Users/mhauck/.rvm/gems/jruby-1.6.5.1/gems/railties-3.0.10/lib/rails/commands/server.rb:65:in `start'
      /Users/mhauck/.rvm/gems/jruby-1.6.5.1/gems/railties-3.0.10/lib/rails/commands.rb:30:in `(root)'
      org/jruby/RubyKernel.java:1804:in `tap'
      /Users/mhauck/.rvm/gems/jruby-1.6.5.1/gems/railties-3.0.10/lib/rails/commands.rb:27:in `(root)'
      org/jruby/RubyKernel.java:1047:in `require'
      script/rails:59:in `(root)'

      The failure in `connect` comes from the following code (from jtv-apns gem):

      context = OpenSSL::SSL::SSLContext.new
      context.cert = cert
      context.key = pem
      sock = TCPSocket.new(host, port)
      ssl = OpenSSL::SSL::SSLSocket.new(sock, context)
      ssl.connect

      PS. I configured webrick to use SSL as detailed here: http://www.nearinfinity.com/blogs/chris_rohr/configuring_webrick_to_use_ssl.html

        Activity

        Hide
        Matt Hauck added a comment -

        Here is a simple ssl server that might to do the trick. I'm not sure if this is the exact same error or not...but whenever I try to connect in chrome, it gives me this:

        IOError: Broken pipe
        syswrite at org/jruby/ext/openssl/SSLSocket.java:621
        do_write at /Users/matt/.rvm/rubies/jruby-1.7.0/lib/ruby/1.9/openssl/buffering.rb:317
        puts at /Users/matt/.rvm/rubies/jruby-1.7.0/lib/ruby/1.9/openssl/buffering.rb:402
        (root) at sslserver.rb:20
        loop at org/jruby/RubyKernel.java:1390
        (root) at sslserver.rb:16

        Show
        Matt Hauck added a comment - Here is a simple ssl server that might to do the trick. I'm not sure if this is the exact same error or not...but whenever I try to connect in chrome, it gives me this: IOError: Broken pipe syswrite at org/jruby/ext/openssl/SSLSocket.java:621 do_write at /Users/matt/.rvm/rubies/jruby-1.7.0/lib/ruby/1.9/openssl/buffering.rb:317 puts at /Users/matt/.rvm/rubies/jruby-1.7.0/lib/ruby/1.9/openssl/buffering.rb:402 (root) at sslserver.rb:20 loop at org/jruby/RubyKernel.java:1390 (root) at sslserver.rb:16
        Hide
        Charles Oliver Nutter added a comment -

        Reproduced here with Matt's server script using a cert + key from our openssl tests. Investigating.

        Show
        Charles Oliver Nutter added a comment - Reproduced here with Matt's server script using a cert + key from our openssl tests. Investigating.
        Hide
        Charles Oliver Nutter added a comment -

        Oddly enough it also fails with 1.9.3 when I hit the server with a browser:

        system ~/projects/jruby $ ruby-1.9.3 ssl-server.rb 
        
        Waiting...
        
        Waiting...
        
        Waiting...
        
        Waiting...
        /usr/local/lib/ruby/1.9.1/openssl/buffering.rb:318:in `syswrite': Broken pipe (Errno::EPIPE)
        	from /usr/local/lib/ruby/1.9.1/openssl/buffering.rb:318:in `do_write'
        	from /usr/local/lib/ruby/1.9.1/openssl/buffering.rb:403:in `puts'
        	from ssl-server.rb:20:in `block in <main>'
        	from ssl-server.rb:16:in `loop'
        	from ssl-server.rb:16:in `<main>'
        

        In the MRI case, the two strings do get sent to the browser, but that could just be buffering/flushing behavior difference. JRuby does fail during the second write.

        Show
        Charles Oliver Nutter added a comment - Oddly enough it also fails with 1.9.3 when I hit the server with a browser: system ~/projects/jruby $ ruby-1.9.3 ssl-server.rb Waiting... Waiting... Waiting... Waiting... /usr/local/lib/ruby/1.9.1/openssl/buffering.rb:318:in `syswrite': Broken pipe (Errno::EPIPE) from /usr/local/lib/ruby/1.9.1/openssl/buffering.rb:318:in `do_write' from /usr/local/lib/ruby/1.9.1/openssl/buffering.rb:403:in `puts' from ssl-server.rb:20:in `block in <main>' from ssl-server.rb:16:in `loop' from ssl-server.rb:16:in `<main>' In the MRI case, the two strings do get sent to the browser, but that could just be buffering/flushing behavior difference. JRuby does fail during the second write.
        Hide
        Charles Oliver Nutter added a comment -

        Ok, even more confusing...one time I got the above output from JRuby too, indicating that it was able to send all the data but closed earlier than expected?

        Show
        Charles Oliver Nutter added a comment - Ok, even more confusing...one time I got the above output from JRuby too, indicating that it was able to send all the data but closed earlier than expected?
        Hide
        Charles Oliver Nutter added a comment -

        Ok, I think this is actually a browser interaction issue and not a bug in SSL.

        Because I was sometimes getting successful responses using MRI, I started to question whether the server was the problem. So, on a hunch, I added a one-second sleep to the server after accepting the incoming socket. With that sleep, MRI fails every time.

        I think what we're seeing here is an interaction between the SSL server wanting to immediately write content and the browser sending its HTTP request. If the request starts before the server's write begins (and perhaps also during) the browser appears to shut down the connection. This causes the "broken pipe" error, since the client side has gone away and the server is still up.

        It works sometimes because some browsers will sometimes show what the server wrote, even if it's not a proper HTTP response. It seems to be all about timing.

        JRuby fails it more frequently than MRI probably because at startup we're a bit slower to get to the writing.

        I would recommend attempting to reproduce this with an SSL client that is not a browser. If you can do that, and there's still a problem, please reopen.

        Show
        Charles Oliver Nutter added a comment - Ok, I think this is actually a browser interaction issue and not a bug in SSL. Because I was sometimes getting successful responses using MRI, I started to question whether the server was the problem. So, on a hunch, I added a one-second sleep to the server after accepting the incoming socket. With that sleep, MRI fails every time. I think what we're seeing here is an interaction between the SSL server wanting to immediately write content and the browser sending its HTTP request. If the request starts before the server's write begins (and perhaps also during) the browser appears to shut down the connection. This causes the "broken pipe" error, since the client side has gone away and the server is still up. It works sometimes because some browsers will sometimes show what the server wrote, even if it's not a proper HTTP response. It seems to be all about timing. JRuby fails it more frequently than MRI probably because at startup we're a bit slower to get to the writing. I would recommend attempting to reproduce this with an SSL client that is not a browser. If you can do that, and there's still a problem, please reopen.

          People

          • Assignee:
            Charles Oliver Nutter
            Reporter:
            Matt Hauck
          • Votes:
            3 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: