Skip to content

Commit

Permalink
Unlock if poll triggers an exception
Browse files Browse the repository at this point in the history
CRuby semantics for an interrupt during lock appear to ensure that
the lock is released before propagating any interrupt exception.
This poll was added without such behavior, leading to locks being
left locked even though a thread interrupt happened. This in turn
breaks some semantics of Mutex#synchronize, since the lock call
does not happen within the try/finally that would release it, so
any exception raised will exit synchronize with the lock still
locked.

The fix here wraps the additional poll with try/catch to ensure
poll-triggered exceptions release the lock before propagating.

Fixes jruby#8585
  • Loading branch information
headius committed Jan 22, 2025
1 parent 45e682d commit 6e1ed7c
Showing 1 changed file with 10 additions and 1 deletion.
11 changes: 10 additions & 1 deletion core/src/main/java/org/jruby/ext/thread/Mutex.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Block;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
Expand Down Expand Up @@ -114,7 +115,15 @@ public IRubyObject lock(ThreadContext context) {
}

// always check for thread interrupts after acquiring lock
thread.pollThreadEvents(context);
try {
thread.pollThreadEvents(context);
} catch (Throwable t) {
// Thread poll triggered an exception event, release locked locks before propagating
if (lock.isHeldByCurrentThread()) {
thread.unlock(lock);
}
Helpers.throwException(t);
}

return this;
}
Expand Down

0 comments on commit 6e1ed7c

Please sign in to comment.