Skip to content

Commit

Permalink
Clear interrupt queue when acting on interrupt
Browse files Browse the repository at this point in the history
If we don't clear the queue here and begin to act on a kill or
raise event, we may poll again and find a different event that
invalidate the one we're currently propagating. This led to
intermittent failures on this spec:

Thread#report_on_exception= when set to true prints the backtrace even if the thread was killed just after Thread#raise

This spec tests that a raise event propagates all the way out even
if a kill interrupts that process. It is difficult to simulate
that without clearing the queue, since we poll for new interrupts
many places that might be hit while raising (such as when printing
out the report that an exception terminated the thread).

The risk here is that an event will be lost, but it is unclear if
it should be possible to queue multiple events that trigger stack
unrolling.
  • Loading branch information
headius committed Dec 3, 2024
1 parent 348450a commit dab2510
Showing 1 changed file with 2 additions and 3 deletions.
5 changes: 2 additions & 3 deletions core/src/main/java/org/jruby/RubyThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -331,16 +331,15 @@ private int getInterrupts() {
}

private IRubyObject pendingInterruptDeque(ThreadContext context, int timing) {
for (Iterator<IRubyObject> iterator = pendingInterruptQueue.iterator(); iterator.hasNext();) {
IRubyObject err = iterator.next();
for (IRubyObject err = pendingInterruptQueue.peek(); err != null;) {
int maskTiming = pendingInterruptCheckMask(context, err);

switch (maskTiming) {
case INTERRUPT_ON_BLOCKING:
if (timing != INTERRUPT_ON_BLOCKING) break;
case INTERRUPT_NONE:
case INTERRUPT_IMMEDIATE:
iterator.remove();
pendingInterruptQueue.clear();
return err;
case INTERRUPT_NEVER:
break;
Expand Down

0 comments on commit dab2510

Please sign in to comment.