Skip to content

Commit 20632af

Browse files
committed
Fix RubyThread.join to set "$!" in the calling thread when the target
thread exits with an exception. This lets us gets rid of a hack in both AST and IR interpreters where on catching an exception, "$!" is set before passing control to the rescue handlers. This in turn makes the exception handlers in IR interpreter loop identical for a couple scenarios which can then let us compact exception tables for the IR JIT.
1 parent c762de9 commit 20632af

File tree

3 files changed

+12
-11
lines changed

3 files changed

+12
-11
lines changed

src/org/jruby/RubyThread.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,8 @@ public IRubyObject join(IRubyObject[] args) {
612612
}
613613

614614
if (exitingException != null) {
615+
// Set $! in the current thread before exiting
616+
getRuntime().getGlobalVariables().set("$!", (IRubyObject)exitingException.getException());
615617
throw exitingException;
616618
}
617619

src/org/jruby/ast/RescueNode.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,6 @@ private IRubyObject interpretWithJavaExceptions(Ruby runtime, ThreadContext cont
170170

171171
private IRubyObject handleException(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock, RaiseException raiseJump) {
172172
RubyException raisedException = raiseJump.getException();
173-
// TODO: Rubicon TestKernel dies without this line. A cursory glance implies we
174-
// falsely set $! to nil and this sets it back to something valid. This should
175-
// get fixed at the same time we address bug #1296484.
176-
runtime.getGlobalVariables().set("$!", raisedException);
177-
178173
RescueBodyNode cRescueNode = rescueNode;
179174

180175
while (cRescueNode != null) {

src/org/jruby/ir/interpreter/Interpreter.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ private static IRubyObject interpret(ThreadContext context, IRubyObject self,
400400
switch(operation) {
401401
case PUSH_BINDING: {
402402
// SSS FIXME: Blocks are a headache -- so, these instrs. are only added to IRMethods
403-
// They have more complicated logic for pushing a dynamic scope (see InterpretedIRBlockBody)
403+
// Blocks have more complicated logic for pushing a dynamic scope (see InterpretedIRBlockBody)
404404
currDynScope = DynamicScope.newDynamicScope(scope.getStaticScope());
405405
context.pushScope(currDynScope);
406406
ipc++;
@@ -620,11 +620,6 @@ private static IRubyObject interpret(ThreadContext context, IRubyObject self,
620620
if (ipc == -1) throw re; // No one rescued exception, pass it on!
621621

622622
exception = re.getException();
623-
// SSS: Copied this comment and line from ast/RescueNode.java:handleException
624-
// TODO: Rubicon TestKernel dies without this line. A cursory glance implies we
625-
// falsely set $! to nil and this sets it back to something valid. This should
626-
// get fixed at the same time we address bug #1296484.
627-
runtime.getGlobalVariables().set("$!", (IRubyObject)exception);
628623
} catch (Throwable t) {
629624
if (t instanceof Unrescuable) {
630625
// ThreadKill, RubyContinuation, MainExitException, etc.
@@ -660,6 +655,15 @@ private static void handleNonLocalReturn(ThreadContext context, IRScope scope, R
660655

661656
if (inClosure) {
662657
if (methodToReturnFrom == null) {
658+
// SSS FIXME: As Tom correctly pointed out, this is not correct. The example that breaks this code is:
659+
//
660+
// jruby -X-CIR -e "Thread.new { Proc.new { return }.call }.join"
661+
//
662+
// This should report a LocalJumpError, not a ThreadError.
663+
//
664+
// The right fix would involve checking the closure to see who it is associated with.
665+
// If it is a thread-body, it would be a ThreadError. If not, it would be a local-jump-error
666+
// This requires having access to the block -- same requirement as in handleBreakJump.
663667
if (context.getThread() == context.getRuntime().getThreadService().getMainThread()) {
664668
throw IRException.RETURN_LocalJumpError.getException(context.getRuntime());
665669
} else {

0 commit comments

Comments
 (0)