Stack Exchange
JRuby - second call of method "eval" gives (Errno::EBADF) Bad file descriptor
I have a JRuby engine which calls a method "run_code" from a Ruby class. The "run_code" method calls an IRB command and capture its output. 
The first call of method "run_code" works fine everytime.
The second call gives me these error : 
(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(&lt;script&gt;:28) 

The third call gives me these error :
(NoMethodError) undefined method `to_i' for #&lt;StringIO:0x128ef465   

Problem accessing /shell. Reason:                                                                
(NoMethodError) undefined method `to_i' for #&lt;StringIO:0x128ef465&gt;
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 #&lt;Str
ingIO:0x128ef465&gt;                                                                                                                                                                              
Caused by:org.jruby.exceptions.RaiseException: (NoMethodError) undefined method `to_i'
 for #&lt;StringIO:0x128ef465&gt;                                                                   
 at Engine.run_code(&lt;script&gt;:12)                                       

My java code looks like this : 
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";
}

My ruby code looks like this:
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

Do you know what could be the problem?
Instead of creating a new $stdout object I kept a reference to the old one. Now it gives me 
    javax.script.ScriptException: org.jruby.exceptions.RaiseException: (Errno::
EBADF) Bad file descriptor   

error. 

I would initially suggest doing something like this, as it has fixed this same error for me in the past:
ScriptingContainer container = new ScriptingContainer();
try {
    Reader reader = new FileReader(myEngine);
    // rest of your code here...
} finally {
    container.terminate();
}

