Skip to content
This repository

Fix edge case where rescued Exceptions may be nil #311

Merged
merged 1 commit into from over 1 year ago

3 participants

Ben Browning subbuss Charles Oliver Nutter
Ben Browning

If an inner rescue block causes a Java proxy or package to be looked
up then an outer rescue block was receiving a nil Exception object,
only when running in interpretered, non-IR mode. Running the test with
"-X+C" or "-X-CIR" did not reproduce the behavior.

This behavior was introduced by the commits 20632af and 7c3f642,
which were cleaning up a hack around the way $! got set. The mentioned
hack was covering up this bug.

Ben Browning Fix edge case where rescued Exceptions may be nil
If an inner rescue block causes a Java proxy or package to be looked
up then an outer rescue block was receiving a nil Exception object,
only when running in interpretered, non-IR mode. Running the test with
"-X+C" or "-X-CIR" did not reproduce the behavior.

This behavior was introduced by the commits 20632af and 7c3f642,
which were cleaning up a hack around the way $! got set. The mentioned
hack was covering up this bug.
df7874f
subbuss
Collaborator

Thanks Ben.

The reason -X+C doesn't have this bug is because I did not clean up the JIT to remove the $! hack as I did with -X-CIR and -X-C (See commit log note in 7c3f642). Curious why this example doesn't fail in -X-CIR mode since IR doesn't have the $! hack either. I do know that in IR mode, $! is saved and restored properly in IR-generated code, so maybe the clobbering in the runtime does not matter ... but just a guess.

The bigger issue that this bug exposes is that "$!" is a proxy for the errorInfo value in ThreadContext and so, $! can be modified indirectly by directly calling setErrorInfo. Ideally, in later commits, we should do the following:

  • clean up the JIT to get rid of the $! hack as done for the AST interp in 20632af
  • audit all uses of setErrorInfo to see if they clobber $! accidentally anywhere else.
  • unify the globalVariables.set("$!", foo) and setErrorInfo(foo) paths so that we use one or the other uniformly, if feasible.
Charles Oliver Nutter headius merged commit 4f2c44e into from September 26, 2012
Charles Oliver Nutter headius closed this September 26, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Sep 25, 2012
Ben Browning Fix edge case where rescued Exceptions may be nil
If an inner rescue block causes a Java proxy or package to be looked
up then an outer rescue block was receiving a nil Exception object,
only when running in interpretered, non-IR mode. Running the test with
"-X+C" or "-X-CIR" did not reproduce the behavior.

This behavior was introduced by the commits 20632af and 7c3f642,
which were cleaning up a hack around the way $! got set. The mentioned
hack was covering up this bug.
df7874f
This page is out of date. Refresh to see the latest.
18  spec/regression/GH-311_rescue_nil_exception.rb
... ...
@@ -0,0 +1,18 @@
  1
+require 'rspec'
  2
+
  3
+describe 'nested rescue of java exception' do
  4
+  it 'should not have a nil exception' do
  5
+    caught = false
  6
+    begin
  7
+      begin
  8
+        raise 'success'
  9
+      rescue javax.naming.NameNotFoundException
  10
+      end
  11
+    rescue Exception => ex
  12
+      ex.should_not be_nil
  13
+      ex.message.should == 'success'
  14
+      caught = true
  15
+    end
  16
+    caught.should be_true
  17
+  end
  18
+end
3  src/org/jruby/javasupport/Java.java
@@ -919,12 +919,13 @@ private static RubyModule getProxyOrPackageUnderPackage(ThreadContext context, f
919 919
             // this covers the rare case of lower-case class names (and thus will
920 920
             // fail 99.999% of the time). fortunately, we'll only do this once per
921 921
             // package name. (and seriously, folks, look into best practices...)
  922
+            IRubyObject previousErrorInfo = RuntimeHelpers.getErrorInfo(runtime);
922 923
             try {
923 924
                 return getProxyClass(runtime, JavaClass.forNameQuiet(runtime, fullName));
924 925
             } catch (RaiseException re) { /* expected */
925 926
                 RubyException rubyEx = re.getException();
926 927
                 if (rubyEx.kind_of_p(context, runtime.getStandardError()).isTrue()) {
927  
-                    RuntimeHelpers.setErrorInfo(runtime, runtime.getNil());
  928
+                    RuntimeHelpers.setErrorInfo(runtime, previousErrorInfo);
928 929
                 }
929 930
             } catch (Exception e) { /* expected */ }
930 931
 
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.