Index: src/org/jruby/evaluator/ASTInterpreter.java =================================================================== --- src/org/jruby/evaluator/ASTInterpreter.java (revision 4781) +++ src/org/jruby/evaluator/ASTInterpreter.java (working copy) @@ -1431,6 +1431,10 @@ // get fixed at the same time we address bug #1296484. runtime.getGlobalVariables().set("$!", raisedException); + if (runtime.fastGetClass("SystemExit") == raisedException.getMetaClass()) { + throw raiseJump; + } + RescueBodyNode rescueNode = iVisited.getRescueNode(); while (rescueNode != null) { Index: src/org/jruby/RubyThread.java =================================================================== --- src/org/jruby/RubyThread.java (revision 4781) +++ src/org/jruby/RubyThread.java (working copy) @@ -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.getMetaClass() == 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 4781) +++ src/org/jruby/Ruby.java (working copy) @@ -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 4781) +++ src/org/jruby/RubySystemExit.java (working copy) @@ -51,6 +51,14 @@ 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); status = runtime.getNil(); @@ -81,4 +89,4 @@ return getRuntime().getFalse(); } -} \ No newline at end of file +} Index: src/org/jruby/compiler/impl/StandardASMCompiler.java =================================================================== --- src/org/jruby/compiler/impl/StandardASMCompiler.java (revision 4781) +++ src/org/jruby/compiler/impl/StandardASMCompiler.java (working copy) @@ -2354,6 +2354,18 @@ 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() { + method.invokevirtual(cg.p(RubyException.class), "getMetaClass", cg.sig(RubyClass.class)); + loadRuntime(); + method.ldc("SystemExit"); + method.invokevirtual(cg.p(Ruby.class), "getClass", cg.sig(RubyClass.class, String.class)); + Label ifEnd = new Label(); + method.if_acmpne(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 4781) +++ src/org/jruby/compiler/ASTCompiler.java (working copy) @@ -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 4781) +++ src/org/jruby/compiler/MethodCompiler.java (working copy) @@ -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); }