Index: jruby/test/testException.rb =================================================================== --- jruby/test/testException.rb (revision 2591) +++ jruby/test/testException.rb (working copy) @@ -74,4 +74,28 @@ test_no_exception { e = StandardError.new e.set_backtrace(nil) -} \ No newline at end of file +} + +begin + raise 'Something bad' +rescue + begin + test_ok(true) + rescue + test_ok(false) + end + test_ok($!, 'Global exception ($!) should not be nil') + test_ok($!.to_s.eql? 'Something bad', "Global exceptions should be 'Something bad', but is '#{$!}'") +end + +begin + raise 'Something bad' +rescue + begin + raise 'Something else bad' + rescue + test_ok(true) + end + test_ok($!, 'Global exception ($!) should not be nil') + test_ok($!.to_s.eql? 'Something bad', "Global exceptions should be 'Something bad', but is '#{$!}'") +end \ No newline at end of file Index: jruby/src/org/jruby/evaluator/EvaluationState.java =================================================================== --- jruby/src/org/jruby/evaluator/EvaluationState.java (revision 2591) +++ jruby/src/org/jruby/evaluator/EvaluationState.java (working copy) @@ -1170,6 +1170,8 @@ case NodeTypes.RESCUENODE: { RescueNode iVisited = (RescueNode)node; RescuedBlock : while (true) { + IRubyObject globalExceptionState = runtime.getGlobalVariables().get("$!"); + boolean anotherExceptionRaised = false; try { // Execute rescue block IRubyObject result = evalInternal(context, iVisited.getBodyNode(), self); @@ -1189,7 +1191,7 @@ // falsely set $! to nil and this sets it back to something valid. This should // get fixed at the same time we address bug #1296484. runtime.getGlobalVariables().set("$!", raisedException); - + RescueBodyNode rescueNode = iVisited.getRescueNode(); while (rescueNode != null) { @@ -1213,6 +1215,7 @@ continue RescuedBlock; } else { + anotherExceptionRaised = true; throw je; } } @@ -1225,7 +1228,8 @@ throw raiseJump; } finally { // clear exception when handled or retried - runtime.getGlobalVariables().set("$!", runtime.getNil()); + if (!anotherExceptionRaised) + runtime.getGlobalVariables().set("$!", globalExceptionState); } } }