JRuby

next in an eval should produce a local jump error

Details

  • Type: Bug Bug
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: JRuby 1.0.0RC1, JRuby 1.0.0RC2
  • Fix Version/s: JRuby 1.x+
  • Component/s: Interpreter
  • Labels:
    None
  • Testcase included:
    yes
  • Number of attachments :
    0

Description

For code:

eval "next 1"

Ruby output:

-e:1: (eval):1: unexpected next (LocalJumpError)

JRuby output:

Exception in thread "main" org.jruby.exceptions.JumpException

Issue Links

Activity

Hide
Charles Oliver Nutter added a comment -

The big problem here, as explained to me by Tom, is that we propagate what would be LocalJumpErrors as though they're just normal JumpExceptions. Because they're JumpExceptions instead of RaiseExceptions, they don't get caught by rescue blocks.

There are two potential fixes for this I can see:

  • determine at event time (when next or return or whatever happens) whether it should actually raise a LocalJumpError, perhaps because no jump target is available, or the target frame is not listed as "returnable".
  • make JumpException a RaiseException of type LocalJumpError. This would slow down event processing designed to pass through rescue blocks, however, since all rescues would have to be tested against a JumpException they are not intended to handle.

I believe the former is the correct route, and it's likely the only way that MRI could be doing this. So we need to look at these cases one by one and determine where and when it is inappropriate to encounter them, raising a LocalJumpError instead of a JumpException in those cases.

Bumping to 1.0, since we're the only ones that have reported this. But we should fix for 1.0.

Show
Charles Oliver Nutter added a comment - The big problem here, as explained to me by Tom, is that we propagate what would be LocalJumpErrors as though they're just normal JumpExceptions. Because they're JumpExceptions instead of RaiseExceptions, they don't get caught by rescue blocks. There are two potential fixes for this I can see:
  • determine at event time (when next or return or whatever happens) whether it should actually raise a LocalJumpError, perhaps because no jump target is available, or the target frame is not listed as "returnable".
  • make JumpException a RaiseException of type LocalJumpError. This would slow down event processing designed to pass through rescue blocks, however, since all rescues would have to be tested against a JumpException they are not intended to handle.
I believe the former is the correct route, and it's likely the only way that MRI could be doing this. So we need to look at these cases one by one and determine where and when it is inappropriate to encounter them, raising a LocalJumpError instead of a JumpException in those cases. Bumping to 1.0, since we're the only ones that have reported this. But we should fix for 1.0.
Hide
Charles Oliver Nutter added a comment -

Not going to be in RC2, but since it's a language compat issue we'd like to still get it working for 1.0 final.

Show
Charles Oliver Nutter added a comment - Not going to be in RC2, but since it's a language compat issue we'd like to still get it working for 1.0 final.
Hide
Charles Oliver Nutter added a comment -

Both related to handling of JumpException vs LocalJumpError.

Show
Charles Oliver Nutter added a comment - Both related to handling of JumpException vs LocalJumpError.
Hide
Marcin Mielzynski added a comment - - edited

they don't have to be in an eval and there's others:

return / eval "return"
(eval):1: unexpected return (LocalJumpError) // this one works in jruby now (was considered toplevel return in previous JIRAs)
break / eval "break"
(eval):1: unexpected break (LocalJumpError)
redo / eval "redo"
(eval):1: unexpected redo (LocalJumpError)

retry / eval "retry"
1: retry outside of rescue clause

throw / eval "throw" results in:
RubyKernel.java:778:in `org.jruby.RubyKernel.rbThrow': java.lang.ArrayIndexOutOfBoundsException: 0 (NativeException)
should be: 3:in `throw': wrong number of arguments (0 for 1) (ArgumentError)
there's also warn_printf(": unexpected throw\n"); - but couldn't reproduce that.

All those errors are fixed strings in eval.c:error_handle(ex) called by eval.c:ruby_options(...), eval.c:ruby_cleanup(...) and eval.c:rb_exec_end_proc() thrown on condition: if ((status = EXEC_TAG()) != 0).

Tried to dive more into it but some things are not clear for me yet.

Show
Marcin Mielzynski added a comment - - edited they don't have to be in an eval and there's others: return / eval "return" (eval):1: unexpected return (LocalJumpError) // this one works in jruby now (was considered toplevel return in previous JIRAs) break / eval "break" (eval):1: unexpected break (LocalJumpError) redo / eval "redo" (eval):1: unexpected redo (LocalJumpError) retry / eval "retry" 1: retry outside of rescue clause throw / eval "throw" results in: RubyKernel.java:778:in `org.jruby.RubyKernel.rbThrow': java.lang.ArrayIndexOutOfBoundsException: 0 (NativeException) should be: 3:in `throw': wrong number of arguments (0 for 1) (ArgumentError) there's also warn_printf(": unexpected throw\n"); - but couldn't reproduce that. All those errors are fixed strings in eval.c:error_handle(ex) called by eval.c:ruby_options(...), eval.c:ruby_cleanup(...) and eval.c:rb_exec_end_proc() thrown on condition: if ((status = EXEC_TAG()) != 0). Tried to dive more into it but some things are not clear for me yet.
Hide
Marcin Mielzynski added a comment -

gah, for some reason my previous post turned into viewable only by devs, can it be reverted ?

Show
Marcin Mielzynski added a comment - gah, for some reason my previous post turned into viewable only by devs, can it be reverted ?
Hide
Charles Oliver Nutter added a comment -

Edited Marcin's comment to be visible to all...and it lists a few good cases for which we should be raising LocalJumpError. Can we fix this a little better in a day?

Show
Charles Oliver Nutter added a comment - Edited Marcin's comment to be visible to all...and it lists a few good cases for which we should be raising LocalJumpError. Can we fix this a little better in a day?
Hide
Charles Oliver Nutter added a comment -

Nontrivial, not externally reported. Punting to post 1.0.

Show
Charles Oliver Nutter added a comment - Nontrivial, not externally reported. Punting to post 1.0.
Hide
Charles Oliver Nutter added a comment -

Fix for 1.1 along with JRUBY-966.

Show
Charles Oliver Nutter added a comment - Fix for 1.1 along with JRUBY-966.
Hide
Charles Oliver Nutter added a comment -

Punting issues from 1.1 RC2 to 1.1 final.

Show
Charles Oliver Nutter added a comment - Punting issues from 1.1 RC2 to 1.1 final.
Hide
Charles Oliver Nutter added a comment -

Still not externally reported and still nontrivial to fix. Post 1.1.

Show
Charles Oliver Nutter added a comment - Still not externally reported and still nontrivial to fix. Post 1.1.
Hide
Ivo Wever added a comment - - edited

Behavior in 1.5.6 is different: next, return and retry still have problems (but different problems). break, redo and throw have been fixed.

jruby -e "eval 'next 1'; puts 'after'"
=> 'after' is not printed. No error or exception; silent exit.

jruby -e "eval 'return'; puts 'after'"
=> behaves the same as 'next'

jruby -e "eval 'retry'; puts 'after'"
=> behaves the same as 'next' and 'return'

jruby -e "eval 'break'"
=> :1: unexpected break (LocalJumpError)

jruby -e "eval 'redo'"
:1: unexpected redo (LocalJumpError)

jruby -e "eval 'throw'; puts 'after'"
=> (eval):1:in `throw': wrong # of arguments(0 for 1) (ArgumentError)

Show
Ivo Wever added a comment - - edited Behavior in 1.5.6 is different: next, return and retry still have problems (but different problems). break, redo and throw have been fixed. jruby -e "eval 'next 1'; puts 'after'" => 'after' is not printed. No error or exception; silent exit. jruby -e "eval 'return'; puts 'after'" => behaves the same as 'next' jruby -e "eval 'retry'; puts 'after'" => behaves the same as 'next' and 'return' jruby -e "eval 'break'" => :1: unexpected break (LocalJumpError) jruby -e "eval 'redo'" :1: unexpected redo (LocalJumpError) jruby -e "eval 'throw'; puts 'after'" => (eval):1:in `throw': wrong # of arguments(0 for 1) (ArgumentError)

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated: