RFR: In rare cases, the unlock() on join() might fail, causing an IllegalMonitorStateException

Alan Bateman alanb at openjdk.java.net
Thu Feb 25 12:07:48 UTC 2021


On Thu, 25 Feb 2021 11:10:41 GMT, kabutz <github.com+332398+kabutz at openjdk.org> wrote:

> Unlike synchronized/wait, the Condition.await() method does not necessarily reacquire the lock on exit, for example if the thread is stopped or if CTRL+C is caused in jshell. In that case we would enter the finally block without the lock held and unlocking would cause an IllegalMonitorStateException.
> 
> For example, run the following code from jshell and then press CTRL+C:
> 
> Object monitor = new Object();
> for (int i = 0; i < 10_000; i++) {
>   Thread.startVirtualThread(() -> {
>     synchronized (monitor) {
>       try {
>         monitor.wait();
>       } catch (InterruptedException ignore) {}
>     }
>   });
> }
> Thread.startVirtualThread(() -> System.out.println("done")).join();
> 
> Output is:
> 
> |  Exception java.lang.IllegalMonitorStateException
> |        at ReentrantLock$Sync.tryRelease (ReentrantLock.java:175)
> |        at AbstractQueuedSynchronizer.release (AbstractQueuedSynchronizer.java:1007)
> |        at ReentrantLock.unlock (ReentrantLock.java:494)
> |        at VirtualThread.joinNanos (VirtualThread.java:635)
> |        at Thread.join (Thread.java:2281)
> |        at Thread.join (Thread.java:2366)
> |        at (#3:1)

I'm in two minds about point fixes to improve robustness with Thread.stop. In this case, there are other usages of Condition::await, including some of the blocking queue implementations in j.u.concurrent, that probably have the same issue.

We want Thread::stop to go away. We terminally deprecated and degraded stop(Throwable) in Java 9 and finally removed the method in a later release, the no-arg Thread::stop needs to go the same way. The first steps for this are in the loom repo in the form of terminal deprecation, not supported for virtual threads, and ThreadGroup::stop degraded to unconditionally throw UOE. We've been hesitant to be move faster as there may be usages in the wild where it is used instead of interrupt as a cancellation mechanism.

I should also say that debugger support (JDI/JDWP,JVMTI) has the equivalent of stop(Throwable) for "managed" usages of async exceptions. jshell uses a signal interrupt and JDI and maybe it's calling Thread.stop, I need to check that as I can't otherwise explain why you see an issue with ctrl-C in jshell.

-------------

PR: https://git.openjdk.java.net/loom/pull/32


More information about the loom-dev mailing list