JRuby - 方法“eval”的第二次调用给出(Errno :: EBADF)Bad文件描述符

时间:2012-07-16 17:25:21

标签: java ruby-on-rails ruby file jruby

我有一个JRuby引擎,它从Ruby类调用方法“run_code”。 “run_code”方法调用IRB命令并捕获其输出。

方法“run_code”的第一次调用每次都能正常工作。

第二次调用给了我这些错误:

(Errno::EBADF) Bad file descriptor 
Caused by: org.jruby.embed.InvokeFailedException: (Errno::EBADF) Bad file descriptor                                                  
     at org.jruby.embed.internal.EmbedRubyObjectAdapterImpl.call(EmbedRubyObjectAdapterImpl.java:406)   
     at org.jruby.embed.internal.EmbedRubyObjectAdapterImpl.callMethod(EmbedRubyObjectAdapterImpl.java:3
    33)                                                                                                 
     at org.jruby.embed.ScriptingContainer.callMethod(ScriptingContainer.java:1334)                     
     at org.apache.hadoop.hbase.master.ShellEndPoint.commandResponse(ShellEndPoint.java:87)             
     at org.apache.hadoop.hbase.master.ShellEndPoint.doGet(ShellEndPoint.java:114)                      
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)                                    
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)                                    
     at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)                          
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1221)         
     at org.apache.hadoop.http.HttpServer$QuotingInputFilter.doFilter(HttpServer.java:835)              
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1212)         
     at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:399)                        
     at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)                     
     at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)                        
     at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)                        
     at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450)                           
     at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)    
     at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)                        
     at org.mortbay.jetty.Server.handle(Server.java:326)                                                
     at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)                         
     at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:928)         
     at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)                                     
     at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)                                
     at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)                                
     at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)                    
     at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)                   
    Caused by: org.jruby.exceptions.RaiseException: (Errno::EBADF) Bad file descriptor                  
    Caused by:org.jruby.exceptions.RaiseException: (Errno::EBADF) Bad file descriptor     
     at org.jruby.RubyIO.initialize(org/jruby/RubyIO.java:981)                                          
     at org.jruby.RubyIO.new(org/jruby/RubyIO.java:868)                                                 
     at Engine.run_code(<script>:28) 

第三次调用给了我这些错误:

(NoMethodError) undefined method `to_i' for #<StringIO:0x128ef465   

Problem accessing /shell. Reason:                                                                
(NoMethodError) undefined method `to_i' for #<StringIO:0x128ef465>
Caused by: org.jruby.embed.InvokeFailedException: (NoMethodError) undefined method `to_i' for StringIO:0x128ef465;                                                                          
 at org.jruby.embed.internal.EmbedRubyObjectAdapterImpl.call(EmbedRubyObjectAdapterImpl.java:406)   
 at org.jruby.embed.internal.EmbedRubyObjectAdapterImpl.callMethod(EmbedRubyObjectAdapterImpl.java:3
33)                                                                                                 
 at org.jruby.embed.ScriptingContainer.callMethod(ScriptingContainer.java:1334)                     
 at org.apache.hadoop.hbase.master.ShellEndPoint.commandResponse(ShellEndPoint.java:87)             
 at org.apache.hadoop.hbase.master.ShellEndPoint.doGet(ShellEndPoint.java:114)                      
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)                                    
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)                                    
 at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)                          
 at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1221)         
 at org.apache.hadoop.http.HttpServer$QuotingInputFilter.doFilter(HttpServer.java:835)              
 at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1212)         
 at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:399)                        
 at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)                     
 at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)                        
 at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)                        
 at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450)                           
 at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)    
 at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)                        
 at org.mortbay.jetty.Server.handle(Server.java:326)                                                
 at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)                         
 at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:928)         
 at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)                                     
 at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)                                
 at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)                                
 at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)                    
 at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)                   
Caused by: org.jruby.exceptions.RaiseException: (NoMethodError) undefined method `to_i' for #<Str
ingIO:0x128ef465>                                                                                                                                                                              
Caused by:org.jruby.exceptions.RaiseException: (NoMethodError) undefined method `to_i'
 for #<StringIO:0x128ef465>                                                                   
 at Engine.run_code(<script>:12)                                       

我的 java代码如下所示:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
ScriptingContainer container = new ScriptingContainer();

Reader reader = new FileReader(myEngine);

try {
  receiver = engine.eval(reader);
  ob = container.callMethod(receiver,"run_code",command);
  response = ob.toString();
} catch(ScriptException e) {
      LOG.debug(e.getMessage());
      response ="ERROR";
}

我的红宝石代码如下所示:

require 'stringio'
require 'irb'
require 'hirb'

class Engine
  extend Shell
  def initialize()
    @binding = Kernel.binding
  end
  def run_code(code)
    # run something
    stdout_id = $stdout.to_i
    $stdout = StringIO.new
    cmd = <<-EOF
    $stdout = StringIO.new
    begin
      #{code}
    end
    EOF
    begin
      result = Thread.new { Kernel.eval(cmd, @binding) }.value
    rescue SecurityError
      return "illegal"
    rescue Exception => e
      return e
    ensure
      output = get_stdout
      $stdout = IO.new(stdout_id)
    end

    return output
  end

   private
   def get_stdout
     raise TypeError, "$stdout is a #{$stdout.class}" unless $stdout.is_a? StringIO
     $stdout.rewind
     $stdout.read
   end

end

module Kernel
  @shell = Shell::Shell.new(@hbase, @formatter)

  # Add commands to this namespace
  @shell.export_commands(self)
  @formatter = Shell::Formatter::Console.new

  # Setup the HBase module.  Create a configuration.
  @hbase = Hbase::Hbase.new

  # Setup console
  @shell = Shell::Shell.new(@hbase, @formatter)

  # Add commands to this namespace
  @shell.export_commands(self)

  # Add help command
  def help(command = nil)
    @shell.help(command)
  end

# Backwards compatibility method
  def tools
    @shell.help_group('tools')
  end
end

你知道可能是什么问题吗?

我没有创建一个新的$ stdout对象,而是保留了对旧对象的引用。现在它给了我

    javax.script.ScriptException: org.jruby.exceptions.RaiseException: (Errno::
EBADF) Bad file descriptor   

错误。

1 个答案:

答案 0 :(得分:0)

我最初建议做这样的事情,因为它在过去为我修复了同样的错误:

ScriptingContainer container = new ScriptingContainer();
try {
    Reader reader = new FileReader(myEngine);
    // rest of your code here...
} finally {
    container.terminate();
}