JVMTI functions operating on other threads are using MountUnmountDisabler to disable target virtual thread mount/unmount transitions. Virtual threads making JVMTI function calls can be suspended. In such cases, the self-suspend is postponed while the target thread execution is in a context of MountUnmountDisabler (see: JDK-8373366). JVMTI InterruptThread does a Java upcall to j.l.Thread::interrupt() method in a context of MountUnmountDisabler, and so, can be umounted. Unmount is not allowed and blocked while virtual thread is suspended which is a suspend-equivalent.
It is not clear yet what can be a best fix for this.
The following stack trace represents a deadlocked suspended virtual thread interrupting another thread:
"pool-1-thread-1" #26 [1002714] prio=5 os_prio=0 cpu=92.39ms elapsed=480.38s allocated=105K defined_classes=17 tid=0x0000ffff5003b480 _threads_hazard_ptr=0x0000ffff38002990, _nested_threads_hazard_ptr_cnt=0 [0x0000ffff6a963000]
Carrying virtual thread #25
Thread: 0x0000ffff5003b480 [0xf4cda] State: _at_safepoint _at_poll_safepoint 0
JavaThread state: _thread_blocked
at jdk.internal.vm.Continuation.run(java.base@27-internal/Continuation.java:251)
at java.lang.VirtualThread.runContinuation(java.base@27-internal/VirtualThread.java:300)
at java.lang.VirtualThread$$Lambda/0x000000000e0ea970.run(java.base@27-internal/Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@27-internal/ThreadPoolExecutor.java:1090)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@27-internal/ThreadPoolExecutor.java:614)
at java.lang.Thread.runWith(java.base@27-internal/Thread.java:1529)
at java.lang.Thread.run(java.base@27-internal/Thread.java:1516)
Mounted virtual thread #25
at java.lang.VirtualThread.startTransition(java.base@27-internal/Native Method)
at java.lang.VirtualThread.yieldContinuation(java.base@27-internal/VirtualThread.java:552)
at java.lang.VirtualThread.park(java.base@27-internal/VirtualThread.java:760)
at java.lang.System$1.parkVirtualThread(java.base@27-internal/System.java:2296)
at java.util.concurrent.locks.LockSupport.park(java.base@27-internal/LockSupport.java:221)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@27-internal/AbstractQueuedSynchronizer.java:790)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@27-internal/AbstractQueuedSynchronizer.java:1030)
at java.util.concurrent.locks.ReentrantLock$Sync.lock(java.base@27-internal/ReentrantLock.java:154)
at java.util.concurrent.locks.ReentrantLock.lock(java.base@27-internal/ReentrantLock.java:323)
at java.util.concurrent.LinkedBlockingQueue.signalNotEmpty(java.base@27-internal/LinkedBlockingQueue.java:175)
at java.util.concurrent.LinkedBlockingQueue.offer(java.base@27-internal/LinkedBlockingQueue.java:423)
at java.util.concurrent.ThreadPoolExecutor.execute(java.base@27-internal/ThreadPoolExecutor.java:1320)
at java.lang.VirtualThread.submit(java.base@27-internal/VirtualThread.java:330)
at java.lang.VirtualThread.submitRunContinuation(java.base@27-internal/VirtualThread.java:354)
at java.lang.VirtualThread.submitRunContinuation(java.base@27-internal/VirtualThread.java:401)
at java.lang.VirtualThread.unpark(java.base@27-internal/VirtualThread.java:875)
at java.lang.VirtualThread.unpark(java.base@27-internal/VirtualThread.java:901)
at java.lang.VirtualThread.interrupt(java.base@27-internal/VirtualThread.java:1080)
at ThreadStateTest2.testInterruptThread(Native Method)
at ThreadStateTest2.lambda$new$2(ThreadStateTest2.java:84)
at ThreadStateTest2$$Lambda/0x000000000e081680.run(Unknown Source)
at java.lang.Thread.runWith(java.base@27-internal/Thread.java:1529)
at java.lang.VirtualThread.run(java.base@27-internal/VirtualThread.java:475)
at java.lang.VirtualThread$VThreadContinuation$1.run(java.base@27-internal/VirtualThread.java:255)
at jdk.internal.vm.Continuation.enter0(java.base@27-internal/Continuation.java:322)
at jdk.internal.vm.Continuation.enter(java.base@27-internal/Continuation.java:313)
It is not clear yet what can be a best fix for this.
The following stack trace represents a deadlocked suspended virtual thread interrupting another thread:
"pool-1-thread-1" #26 [1002714] prio=5 os_prio=0 cpu=92.39ms elapsed=480.38s allocated=105K defined_classes=17 tid=0x0000ffff5003b480 _threads_hazard_ptr=0x0000ffff38002990, _nested_threads_hazard_ptr_cnt=0 [0x0000ffff6a963000]
Carrying virtual thread #25
Thread: 0x0000ffff5003b480 [0xf4cda] State: _at_safepoint _at_poll_safepoint 0
JavaThread state: _thread_blocked
at jdk.internal.vm.Continuation.run(java.base@27-internal/Continuation.java:251)
at java.lang.VirtualThread.runContinuation(java.base@27-internal/VirtualThread.java:300)
at java.lang.VirtualThread$$Lambda/0x000000000e0ea970.run(java.base@27-internal/Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@27-internal/ThreadPoolExecutor.java:1090)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@27-internal/ThreadPoolExecutor.java:614)
at java.lang.Thread.runWith(java.base@27-internal/Thread.java:1529)
at java.lang.Thread.run(java.base@27-internal/Thread.java:1516)
Mounted virtual thread #25
at java.lang.VirtualThread.startTransition(java.base@27-internal/Native Method)
at java.lang.VirtualThread.yieldContinuation(java.base@27-internal/VirtualThread.java:552)
at java.lang.VirtualThread.park(java.base@27-internal/VirtualThread.java:760)
at java.lang.System$1.parkVirtualThread(java.base@27-internal/System.java:2296)
at java.util.concurrent.locks.LockSupport.park(java.base@27-internal/LockSupport.java:221)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@27-internal/AbstractQueuedSynchronizer.java:790)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@27-internal/AbstractQueuedSynchronizer.java:1030)
at java.util.concurrent.locks.ReentrantLock$Sync.lock(java.base@27-internal/ReentrantLock.java:154)
at java.util.concurrent.locks.ReentrantLock.lock(java.base@27-internal/ReentrantLock.java:323)
at java.util.concurrent.LinkedBlockingQueue.signalNotEmpty(java.base@27-internal/LinkedBlockingQueue.java:175)
at java.util.concurrent.LinkedBlockingQueue.offer(java.base@27-internal/LinkedBlockingQueue.java:423)
at java.util.concurrent.ThreadPoolExecutor.execute(java.base@27-internal/ThreadPoolExecutor.java:1320)
at java.lang.VirtualThread.submit(java.base@27-internal/VirtualThread.java:330)
at java.lang.VirtualThread.submitRunContinuation(java.base@27-internal/VirtualThread.java:354)
at java.lang.VirtualThread.submitRunContinuation(java.base@27-internal/VirtualThread.java:401)
at java.lang.VirtualThread.unpark(java.base@27-internal/VirtualThread.java:875)
at java.lang.VirtualThread.unpark(java.base@27-internal/VirtualThread.java:901)
at java.lang.VirtualThread.interrupt(java.base@27-internal/VirtualThread.java:1080)
at ThreadStateTest2.testInterruptThread(Native Method)
at ThreadStateTest2.lambda$new$2(ThreadStateTest2.java:84)
at ThreadStateTest2$$Lambda/0x000000000e081680.run(Unknown Source)
at java.lang.Thread.runWith(java.base@27-internal/Thread.java:1529)
at java.lang.VirtualThread.run(java.base@27-internal/VirtualThread.java:475)
at java.lang.VirtualThread$VThreadContinuation$1.run(java.base@27-internal/VirtualThread.java:255)
at jdk.internal.vm.Continuation.enter0(java.base@27-internal/Continuation.java:322)
at jdk.internal.vm.Continuation.enter(java.base@27-internal/Continuation.java:313)
- relates to
-
JDK-8373366 HandshakeState should disallow suspend ops for disabler threads
-
- In Progress
-