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