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 2
    • 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 Miel?y?ski 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 Miel?y?ski 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 Miel?y?ski added a comment -

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

          Show
          Marcin Miel?y?ski 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

            • Assignee:
              Charles Oliver Nutter
              Reporter:
              Charles Oliver Nutter
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated: