exception in eval gets written to stderr #145

phdoerfler opened this Issue Apr 26, 2012 · 9 comments


None yet

4 participants



Trying to eval invalid code not only results in an exception (Good!), but in stacktraces written to stderr (Not that good)

The following java code reproduces the bug:

try {
(new javax.script.ScriptEngineManager).getEngineByExtension("rb").eval("1+");
} catch (Exception e) {
// Do nothing

No, I totally would not write such code, but it illustrates the problem quite well. Should not print a single line, but does:

[error] SyntaxError: <script>:1: syntax error, unexpected end-of-file
[error] org.jruby.embed.ParseFailedException: (SyntaxError) <script>:1: syntax error, unexpected end-of-file
[error] at org.jruby.embed.internal.EmbedRubyRuntimeAdapterImpl.runParser(EmbedRubyRuntimeAdapterImpl.java:207)
[error] at org.jruby.embed.internal.EmbedRubyRuntimeAdapterImpl.parse(EmbedRubyRuntimeAdapterImpl.java:93)
[error] at org.jruby.embed.ScriptingContainer.parse(ScriptingContainer.java:1195)
[error] at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:89)
[error] at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:153)

JRuby version is 1.6.7

(Yay for Markdown killing stacktraces)

headius commented Apr 26, 2012

The problem seems to be this code in org.jruby.embed.jsr223.JRubyEngine. I'm not sure why we need to log the output here, since the exception still propagates (in wrapped form) and obviously folks don't like exceptions logging without their knowledge...

    private ScriptException wrapException(Exception e) {
        if (e.getCause() instanceof Exception) {
            Writer w = container.getErrorWriter();
            if (w instanceof PrintWriter) {
                e.printStackTrace((PrintWriter) w);
            } else {
                try {
                } catch (IOException ex) {
                    return new ScriptException(ex);
            return new ScriptException((Exception) e.getCause());
        } else {
            return new ScriptException(e);
@yokolet yokolet was assigned Apr 26, 2012
headius commented Apr 26, 2012

@yokolet Can you explain the printing here?

headius commented Apr 29, 2012

I believe we will remove this. Should happen in the 1.7 timeframe.

qmx commented Apr 29, 2012

@headius should we use the same logger stuff?

headius commented Apr 30, 2012

@qmx Yeah, we could, but would that silence the default case? It seems to me we should just remove the logging and propagate the wrapped exception. We're already propagating the wrapper, but even if you handle it the original will still be logged. I don't see a reason for that.

@headius headius added a commit that closed this issue Apr 30, 2012
@headius headius Remove all places where we unconditionally log exceptions.
Several locations in the embedding APIs unconditionally log
exceptions that are raised to the error stream configured in the
container. They then proceed to throw either the actual exception
or a wrapper, so the user ends up handling it anyway. This causes
expected exceptions to create unnecessary log noise and causes
unexpected exceptions to log twice as much information if they
are not handled by the user.

I have removed all places where exceptions are unconditionally
logged and then subsequently thrown in some form anyway.

Fixes #145.
@headius headius closed this in 5af68df Apr 30, 2012
yokolet commented Apr 30, 2012

This might be against to JSR223 spec. I''l check it up and write here whether the change is OK or not.


Thank's for fixing the issue. I don't know the JSR223 spec, but when using the default Javascript evaluator getEngineByExtension("js"), malformed code does not log an exception, only throws it. That's what I (and others, obviously) expect. I hope JSR223 agrees with that.

headius commented May 5, 2012

@yokolet Let me know if you find anything stating that exceptions should be logged. I did a quick read through the spec and could not find anything to indicate this other than one paragraph:

Each of the operations might result in errors. Operations taking
place in the Java Virtual Machine may throw Exceptions. Each error
must be handled so it can be reported in the output from the script. If
the scripting language has an exception mechanism, Java Exceptions
should be converted to script exceptions and these should be thrown
in the calling script.

I interpret this to mean that exceptions should always be included in some output from a script, such as a raised ScriptException, rather than swallowed. I could not find any other part of the spec that indicated logging of exceptions should always occur.

If you find such a statement, we'll evaluate whether to revert those changes. Thanks for keeping us honest! :)

yokolet commented May 7, 2012

@headius The change looks OK. I read this issue on iPhone since I still don't have ground line of Internet connection and am busy to put things away after a big moving. :( Looking code on iPhone was hard to understand.

For a clarification, let me add a comment.

As you said, JSR223 doesn't have any logging requirement. The spec says a scripting engine should raise checked exceptions. My implementation of logging might have been good for customized environments, which likes logging to some IO rather than getting exceptions. But, I realized it was JRuby specific implementation and should be removed.

It is important for JSR223 imple to work the same as other languages' implementation. So, the change improves compatibility with others.

As for ScriptingContainer, perhaps, "the same logger stuff"(@qmx's comment) should be applied.

@eregon eregon added a commit that referenced this issue Oct 28, 2015
@eregon eregon Squashed 'spec/ruby/' changes from fa9e1cd..92311a8
92311a8 Module#prepend is private in ruby 2.0
e3283d5 Module#include and #prepend should be defined directly on Module
1afea36 Specify TCPServer#accept and #accept_nonblock when closed
c4bb84f Add spec for String#force_encoding called on a frozen string.
0f1e1db Add spec for alias and undef raising a NameError which is not a NoMethodError
86e10f3 New spec for Kernel#exit across threads
dfb2aa0 Refactor a couple Module#prepend specs
a6bd065 Add a spec for Range#dup
8aa7b1e Super from a class method must work with prepended modules.
591ff4f Add a few more specs for defined? with scoped constants.
b99f44c Add a few spec about the return value with ensure
ee87540 Add yield-to-lambda cases that were not all consistent in JRuby.
156bb2b proc.call on object that calls #to_ary which returns nil should return original object
9145998 Add spec for alias on top level
a924c74 Add specs for results of begin-end blocks
193cf30 New spec for setting visibility from a block
f987230 Clarify private spec
22e0298 Add spec for nested methods in a "def expr.meth"
142a876 Add spec for nested methods in instance_eval
8d7b807 Ensure the variable can be read from Binding#eval after Binding#local_variable_set
fe35f8a Actually use a shadowed variable in Binding#local_variables spec
092639a Remove inappropriate spec
842d3aa Fix UnboundMethod#super_method to not be order dependent
bfd0a7e Merge pull request #155 from wied03/master
f6ebc9b Follow up for ruby/spec#153
5b76fa0 Merge pull request #154 from wied03/master
948839f Test struct methods ending in ?, !
adbb7de Exact match for without_test_modules
58f9bad Fix style in Module#ancestors spec
da511ce Merge pull request #153 from wied03/tighten_ancestors
01ba680 Exclude more test modules
278546d Tighten up ancestors specs
c49e802 Add a few more check that methods do not end up defined on Object
a81b5d3 Merge pull request #150 from wied03/instance_eval_class_mod
e27298c Merge pull request #148 from wied03/module_instance_methods
35164b4 Test instance eval/exec on classes and modules
7a45ecb Ensure including a module doesn't prevent instance_methods from working
b188d8e Merge pull request #147 from wied03/multiple_remove_meth
f554ff9 Clarify the file organization
004151e Specify that Class#new yield the new Class
dba4b94 Merge pull request #149 from wied03/mod_class_to_s
98235ef A start at module/class#to_s
4d1cf90 Merge pull request #152 from kachick/struct-new-passes-subclass-to-block
8fdfc4f Add a spec for block parameter in Struct.new
f390fcb Improve definition spaces for some Struct.new behaviors
7df9151 Merge pull request #151 from wied03/struct_with_block
4890c67 Improve struct with block tests
9ff4c13 Fully test multiple remove_methods at once
122e1e1 Merge pull request #145 from wied03/master
6b57785 Another case that wasn't working on Opal
4025c0e Only allow #extend to throw the error in Kernel#extend
7551ce6 Kernel#extend raises a TypeError when the argument is not a Module
df5dfc6 Merge pull request #143 from ruby/elia/unnecessary-mutable-string-use
a7acf82 Object instead of a String for singleton spec
c9cc7ae OpenStruct#new_ostruct_member is now a protected method
1b42fb9 Do not access private internal state in the OpenStruct#new_ostruct_member spec
c7f0b73 remove ruby_bug related to old releases
5786f3a remove duplicate specs Float#<=>.
f5323b8 remove trailing spaces
1508e8b Merge pull request #142 from ruby/elia/time_yday
2463dda Simplify the Time#yday
7472ad9 Test Time#yday for each day of each month
c9ff9cf Merge pull request #141 from ruby/elia/not_match_spec
aa56fe8 Minor fixes
17c66fa Add initial specs for Kernel#!~
391d026 Merge pull request #139 from wied03/master
af22315 Merge pull request #140 from wied03/defined_improve
db9a977 Test more granular defined? scenarios
49012ea Added another exception inspect case that wasn't covered
7512517 Update to latest ruby releases
d50b1bd Fix specdoc in Regexp#options
23585e7 Merge pull request #137 from wied03/master
fcf6a05a Cover another regexp case that was failing in Opal
bde1725 Opal is treating // as if it was created with Regexp.allocate, so add a non encoding based options test of // that it can execute and also test that match fails the same way options does
7819cb3 FreeBSD and NetBSD supports birthtime

git-subtree-dir: spec/ruby
git-subtree-split: 92311a8114663b4ae81a086699c4510271fff1ab
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment