Index: src/org/jruby/evaluator/ASTInterpreter.java =================================================================== --- src/org/jruby/evaluator/ASTInterpreter.java (Revision 4783) +++ src/org/jruby/evaluator/ASTInterpreter.java (Arbeitskopie) @@ -1431,6 +1431,10 @@ // get fixed at the same time we address bug #1296484. runtime.getGlobalVariables().set("$!", raisedException); + if (raisedException.isKindOf(runtime.fastGetClass("SystemExit"))) { + throw raiseJump; + } + RescueBodyNode rescueNode = iVisited.getRescueNode(); while (rescueNode != null) { Index: src/org/jruby/RubyThread.java =================================================================== --- src/org/jruby/RubyThread.java (Revision 4783) +++ src/org/jruby/RubyThread.java (Arbeitskopie) @@ -687,14 +687,16 @@ public void exceptionRaised(RaiseException exception) { assert isCurrent(); - Ruby runtime = exception.getException().getRuntime(); - if (abortOnException(runtime)) { + RubyException rubyException = exception.getException(); + Ruby runtime = rubyException.getRuntime(); + if (rubyException.isKindOf(runtime.fastGetClass("SystemExit"))) { + threadService.getMainThread().raise(new IRubyObject[] {rubyException}, Block.NULL_BLOCK); + } else if (abortOnException(runtime)) { // FIXME: printError explodes on some nullpointer //getRuntime().getRuntime().printError(exception.getException()); - // TODO: Doesn't SystemExit have its own method to make this less wordy.. - RubyException re = RubyException.newException(getRuntime(), getRuntime().fastGetClass("SystemExit"), exception.getMessage()); - re.fastSetInternalVariable("status", getRuntime().newFixnum(1)); - threadService.getMainThread().raise(new IRubyObject[] {re}, Block.NULL_BLOCK); + RubyException systemExit = RubySystemExit.newInstance(runtime, 1); + systemExit.message = rubyException.message; + threadService.getMainThread().raise(new IRubyObject[] {systemExit}, Block.NULL_BLOCK); return; } else if (runtime.getDebug().isTrue()) { runtime.printError(exception.getException()); Index: src/org/jruby/Ruby.java =================================================================== --- src/org/jruby/Ruby.java (Revision 4783) +++ src/org/jruby/Ruby.java (Arbeitskopie) @@ -2185,9 +2185,7 @@ } public RaiseException newSystemExit(int status) { - RubyClass exc = fastGetClass("SystemExit"); - IRubyObject[]exArgs = new IRubyObject[]{newFixnum(status), newString("exit")}; - return new RaiseException((RubyException)exc.newInstance(exArgs, Block.NULL_BLOCK)); + return new RaiseException(RubySystemExit.newInstance(this, status)); } public RaiseException newIOError(String message) { Index: src/org/jruby/RubySystemExit.java =================================================================== --- src/org/jruby/RubySystemExit.java (Revision 4783) +++ src/org/jruby/RubySystemExit.java (Arbeitskopie) @@ -49,7 +49,15 @@ systemExitClass.defineAnnotatedMethods(RubySystemExit.class); return systemExitClass; - } + } + + public static RubySystemExit newInstance(Ruby runtime, int status) { + RubyClass exc = runtime.fastGetClass("SystemExit"); + IRubyObject[] exArgs = new IRubyObject[] { + runtime.newFixnum(status), + runtime.newString("exit") }; + return (RubySystemExit) exc.newInstance(exArgs, Block.NULL_BLOCK); + } protected RubySystemExit(Ruby runtime, RubyClass exceptionClass) { super(runtime, exceptionClass); Index: src/org/jruby/compiler/impl/StandardASMCompiler.java =================================================================== --- src/org/jruby/compiler/impl/StandardASMCompiler.java (Revision 4783) +++ src/org/jruby/compiler/impl/StandardASMCompiler.java (Arbeitskopie) @@ -49,7 +49,6 @@ import org.jruby.RubyFixnum; import org.jruby.RubyFloat; import org.jruby.RubyHash; -import org.jruby.RubyLocalJumpError; import org.jruby.RubyMatchData; import org.jruby.RubyModule; import org.jruby.RubyRange; @@ -2354,6 +2353,19 @@ cg.params(ThreadContext.class, IRubyObject.class, Object.class, String.class, String.class, String[].class, int.class, int.class, int.class, int.class, CallConfiguration.class))); } } + + public void rethrowIfSystemExit() { + loadRuntime(); + method.ldc("SystemExit"); + method.invokevirtual(cg.p(Ruby.class), "fastGetClass", cg.sig(RubyClass.class, String.class)); + method.invokevirtual(cg.p(RubyException.class), "isKindOf", cg.sig(boolean.class, cg.params(RubyModule.class))); + method.iconst_0(); + Label ifEnd = new Label(); + method.if_icmpeq(ifEnd); + loadException(); + method.athrow(); + method.label(ifEnd); + } } public class ASMClosureCompiler extends AbstractMethodCompiler { Index: src/org/jruby/compiler/ASTCompiler.java =================================================================== --- src/org/jruby/compiler/ASTCompiler.java (Revision 4783) +++ src/org/jruby/compiler/ASTCompiler.java (Arbeitskopie) @@ -2778,8 +2778,10 @@ public void branch(MethodCompiler context) { context.loadException(); context.unwrapRaiseException(); + context.duplicateCurrentValue(); context.assignGlobalVariable("$!"); context.consumeCurrentValue(); + context.rethrowIfSystemExit(); compileRescueBody(rescueNode.getRescueNode(), context); } }; Index: src/org/jruby/compiler/MethodCompiler.java =================================================================== --- src/org/jruby/compiler/MethodCompiler.java (Revision 4783) +++ src/org/jruby/compiler/MethodCompiler.java (Arbeitskopie) @@ -452,6 +452,7 @@ public void checkWhenWithSplat(); public void createNewEndBlock(ClosureCallback body); public void runBeginBlock(StaticScope scope, ClosureCallback body); - + public void rethrowIfSystemExit(); + public MethodCompiler chainToMethod(String name, ASTInspector inspector); }