简体   繁体   中英

How to avoid jruby's Bad File Descriptor on openssl?

I'm in a java swing application which has its WebService client implemented in jruby. The use case is User clicks on a button, the corresponding controller opens a new Thread and this thread takes a list from a local DB and for each item of the list runs a jruby script (through ScriptingContainer).

Always the first 2 or 3 calls that jruby does succeed, but then it throws:

org.jruby.embed.EvalFailedException: (Errno::EBADF) Bad file descriptor
at org.jruby.embed.internal.EmbedEvalUnitImpl.run(EmbedEvalUnitImpl.java:133)
at org.jruby.embed.ScriptingContainer.runUnit(ScriptingContainer.java:1264)
at org.jruby.embed.ScriptingContainer.runScriptlet(ScriptingContainer.java:1309)
at com.doctrans.AteaService.createMsgAndSend(AteaService.java:112)
at com.doctrans.AteaService.communicateTransportation(AteaService.java:85)
at com.doctrans.DocTransFacadeImpl.requestAteaCode(DocTransFacadeImpl.java:308)
at com.doctrans.DocTransFacadeImpl.requestAteaLoadStockCodes(DocTransFacadeImpl.java:132)
at com.doctrans.gui.controllers.RoutesCtrl$RequestTask.doInBackground(RoutesCtrl.java:501)
at com.doctrans.gui.controllers.RoutesCtrl$RequestTask.doInBackground(RoutesCtrl.java:1)
at javax.swing.SwingWorker$1.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at javax.swing.SwingWorker.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.jruby.exceptions.RaiseException: (Errno::EBADF) Bad file descriptor
at org.jruby.RubyIO.close(org/jruby/RubyIO.java:2052)
at org.jruby.ext.openssl.SSLSocket.sysclose(org/jruby/ext/openssl/SSLSocket.java:704)
at RUBY.close(jar:file:C:/DocTrans/data/DocTrans-2013.10.07.14.45.jar!/openssl/buffering.rb:447)
at RUBY.close(jar:file:C:/DocTrans/data/DocTrans-2013.10.07.14.45.jar!/net/protocol.rb:76)
at RUBY.transport_request(jar:file:C:/DocTrans/data/DocTrans-2013.10.07.14.45.jar!/net/http.rb:1338)
at RUBY.request(jar:file:C:/DocTrans/data/DocTrans-2013.10.07.14.45.jar!/net/http.rb:1301)
at RUBY.send_envio_documento_transporte(jar:file:C:/DocTrans/data/DocTrans-2013.10.07.14.45.jar!/pt/atea/client.rb:81)
at RUBY.(root)(send_request_for_app.rb:50)

Here is the code which is iterated for each item:

public String createMsgAndSend(RouteInfo routeInfo) throws IOException {
    ScriptingContainer container = new ScriptingContainer(LocalContextScope.CONCURRENT);
    String code = null;
    try {
        container.put("info", new Info());
        container.put("route_info", routeInfo);
        container.put("logger", LoggerFactory.getLogger("RubyClient"));
        container.put("user", UserHolder.getCurrentUser()
                .getUser());
        container.put("pwd", UserHolder.getCurrentUser().getPwd());
        RubyObject response = (RubyObject) container.runScriptlet(
                PathType.CLASSPATH, "send_request_for_app.rb");
        Ruby ruby = container.getRuntime();
        boolean success = response.callMethod("fetch",
                RubySymbol.newSymbol(ruby, "success")).isTrue();
        LOGGER.info("Success?: " + success);
        String error = (String) response.callMethod("fetch",
                RubySymbol.newSymbol(ruby, "error")).asJavaString();
        if (success && error.isEmpty()) {
            code = (String) response.callMethod("fetch",
                    RubySymbol.newSymbol(ruby, "code")).asJavaString();
            LOGGER.info("Response code: " + code);
        } else {
            throw new ServiceException(routeInfo, error);
        }
    } finally {
        if (container != null) {
            container.resetWriter();
            container.resetErrorWriter();
            container.clear();
            container.terminate();
        }
    }
    return code;
}

The jruby net/http code which is throwing exception:

      http= Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true
      http.ssl_version = 'SSLv3'
      http.open_timeout= 5000
      http.cert = OpenSSL::X509::Certificate.new(pem)
      http.key = OpenSSL::PKey::RSA.new(pem, pem_key)
      http.verify_mode = OpenSSL::SSL::VERIFY_PEER
      request = Net::HTTP::Post.new(uri.request_uri)
      http.finish if http.started?

I suspect that this may be related to java threads, but don't know where the problem is. How can I avoid this Bad file descriptor exception?

I answer my own question: It was a bug in the openssl lib. Asked in the jruby mailing list and they recomended to upgrade. Upgrading to JRuby 1.7.5 solved the problem!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM