JRuby Embedding prob: Puts appears to fails with RaiseException: (Errno::EBADF) Bad file descriptor
I am attempting to eval a script after replacing hte default out with my own PrintStream.
ScriptingContainer container = new ScriptingContainer();
container.setOut( my new output target printstream);
container.runScriptlet("puts \"*value*\"";);
Boring wrapper Stacktrace
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.jruby.exceptions.RaiseException: (Errno::EBADF) Bad file descriptor
org.jruby.embed.EvalFailedException: (Errno::EBADF) Bad file descriptor
at org.jruby.embed.internal.EmbedEvalUnitImpl.run(EmbedEvalUnitImpl.java:127)
at org.jruby.embed.ScriptingContainer.runUnit(ScriptingContainer.java:1231)
at org.jruby.embed.ScriptingContainer.runScriptlet(ScriptingContainer.java:1224)
... my boring test case stuff
at sun.reflect.NativeMet开发者_如何学编程hodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
Interesting wrapped exception
org.jruby.exceptions.RaiseException: (Errno::EBADF) Bad file descriptor
at org.jruby.RubyIO.write(org/jruby/RubyIO.java:1319)
at org.jruby.RubyIO.write(org/jruby/RubyIO.java:2297)
at org.jruby.RubyIO.puts(org/jruby/RubyIO.java:2252)
at org.jruby.RubyKernel.puts(org/jruby/RubyKernel.java:522)
at #<Class:0x101e4f266>.(root)(<script>:1)
Note my PrintStream simply prints to a StringBuilder which i then assert against in the test. The PrintStream.checkError() always returns false and given it appends to a StringBuilder it never fails.
Each test does cleanup doing the following to the ScriptingContainer. I added the resetXXX calls just to be nice and the problem persists with or without them.
final ScriptingContainer container = ...
container.resetWriter();
container.resetErrorWriter();
container.terminate();
Update It would appear that running the test alone, everything works, but running the test with puts after another fails because something is screwed. THe strange thing is why is it screwed given i am resetting the writers and terminating the container. Is there anything else i need to kill when i tear down Jruby between tests ?
It would appear my tests were not shutting down my ScriptingContainer. Dumb bug. That said ScriptingContainer.resetWriter() and ScriptingContainer.resetError() dont really work.
public class JRubyShellPutsProblem {
public static void main(String[] args) {
final StringBuilder b = new StringBuilder();
for (int i = 0; i < 3; i++) {
final ScriptingContainer container = new ScriptingContainer(LocalContextScope.CONCURRENT, LocalVariableBehavior.PERSISTENT);
final PrintStream printStream = PrintStreams.printer(Printers.stringBuilder(b), LineEnding.CR, Charset.defaultCharset());
container.setOutput(printStream);
container.setError(printStream); // yes same as out, still works.
container.runScriptlet("puts \"hello" + i + "\"\n");
printStream.flush();
System.out.println(b.toString());
// container.resetWriter(); <-- blows up
// container.resetErrorWriter();
container.terminate();
}
}
}
This works for me (JRuby 1.6.2, Java 1.6.0):
import org.jruby.embed.*;
class HelloWorldApp {
public static void main(String[] args) {
ScriptingContainer container = new ScriptingContainer();
try{
container.setOutput(new java.io.PrintStream("log.txt"));
}
catch (Exception e)
{
System.out.println(e);
}
container.runScriptlet("puts \"*value*\"");
}
}
精彩评论