Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Mutex fixes for interruptibility #5942
This PR contains fixes for some interruptibility issues introduced in JRuby 9.2.8:
WIP until I confirm it's ready.
The original code would immediately error out if a contended lock acquisition were interrupted before it could acquire the lock. This led to a behavioral difference from MRI, which does not raise errors. It is not clear whether that's because locks in MRI can never be truly contended (if the lock is not available the thread is put to sleep and woken by the lock owner) or because they explicitly try again to acquire the lock after waking. In this version of the code, we opt to continue trying to acquire the lock via a loop, unless a thread event like raise or kill tell us to divert from the normal path of execution. The only possible outcomes from interrupting a lock acquisition are to keep trying until we have the lock or error out. This patch opts for the former. Fixes #5875.
Previous logic used the same semaphore to sleep as any other sleep which interfered with code that expected the Mutex to be the lock used. The new logic uses the Mutex's JDK Lock, via a Condition, to do the sleeping. Because it is not possible for us to change the artificial thread status we maintain to "sleep" after the lock is released, this modified logic also introduces a new thread state that indicates that the native JDK thread state should be used. This gets closer to avoiding the racing status. It does not appear to eliminate the race altogether. Fixes #5863.
Fix for #5863 is in.
The second fix introduces a new RubyThread status called "NATIVE", which indicates that the native JDK thread status should be translated into a Ruby thread status. This allows us to use the provided JDK Condition.await, which does the appropriate lock release followed by going into a wait state (via LockSupport.park). This in turn allows the specs to pass that depend on the lock being released by the time the thread status is "sleep".
This fix is also a stepping stone toward eliminating the synthetic Ruby thread statuses. As we go forward we can modify more of these state changes to just defer to the NATIVE status, leaning on the JDK to handle state changes without racing.