Infinite loop in EventQueue.isDispatchThread()
Asked Answered
H

2

15

I have a Java program taking 100% cpu, but seemingly doing nothing.

If I take a thread dump, there are 4 threads (out of a pool of 5) waiting to take a lock.

"Incoming WorkPool 5" - Thread t@363
   java.lang.Thread.State: WAITING
    at sun.misc.Unsafe.park(Native Method)
    - waiting to lock <7212149b> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) owned by "Incoming WorkPool 3" t@354
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:867)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197)
    at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214)
    at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290)
    at java.awt.EventQueue.isDispatchThreadImpl(EventQueue.java:1019)
    at java.awt.EventQueue.isDispatchThread(EventQueue.java:1014)

The thread they are waiting for is RUNNABLE

"Incoming WorkPool 3" - Thread t@354
   java.lang.Thread.State: RUNNABLE
    at java.awt.EventQueue.isDispatchThreadImpl(EventQueue.java:1024)
    at java.awt.EventQueue.isDispatchThread(EventQueue.java:1014)

This is JDK 7.0.25, so it seems one thread is stuck on

EventQueue next = eq.nextQueue;
while (next != null) {
    eq = next;
    next = eq.nextQueue;
}

There are two AWT EventQueue threads, trying to acquire the same pushpoplock.

The VM runs as a service, so it shouldn't try to do AWT stuff, but it's done by a library I'm using.

Any ideas? Can I prevent this from happening?

Thanks!

Hysteria answered 14/4, 2015 at 13:21 Comment(10)
1. did you heard about SecondaryLoop, 2. but "taking 100% cpu, but seemingly doing nothing." talking about JProfiler, 3. without an SSCCE/MCVE isn' answerable, 4. java.awt.EventQueue.isDispatchThreadImpl(EventQueue.java:1019) talking about isEventDispatchThread returns false, or events executed in EDT have no business there 5. no idea, without events from current EDT or exception from RepaintManagerTibbs
1) I hadn't heard about SecondaryLoop before. I 've looked it up but I myself do not use AWT, it's a library I use that calls the method. 2) I have not used JProfiler, I have used JVisualVM, it provided me with the threaddump I have shown snippets of. 3) I cannot reproduce it unfortunately. It was a problem I had in production, all I have is the thread dump, so I cannot provide an SSCCE. 4-5) I'm afraid I don't understand these.Hysteria
Who is setting eq.nextQueue to null? If no one setting it then the loop will run infinitely and CPU 100% is possible. If yes and if it done by some other thread then sq.nextQueue should be volatile. If not this thread may not pick the value since the thread can be cache the value of eq.nextQueue where the loop will run infinitely again and CPU 100% possible.Treen
As far as I can tell, it is initialized to null and only set when using java.awt.EventQueue.push(EventQueue newEventQueue).Hysteria
@Brecht Yperman To add to what Eranda said, if eq and next have been cached by the running thread, then writes to those objects may not be seen. See here for a discussion of what I mean.Crimp
I understand that, thanks, but this is java.awt.EventQueue, I cannot change anything in that code.Hysteria
I guess there are more to those stack traces than you show? If so, please post the entire stacks.Disjoint
while (next != null) { if(next != null){ eq = next; next = eq.nextQueue; } }Meara
why do you have two AWT event queues? There should only ever be one.Lurlene
I don't think there are two queues, there are two threads waiting on a lock.Hysteria
M
1

Is there any possibility that push(EventQueue newEventQueue) is called by your application program and that pushes the same eventQueue? If yes, then, this and its nextQueue will be same objects and they will be running in an endless loop consuming CPU to 100%.

From the stack trace its evident that at least one thread is running. So its not a question of DEADLOCK.

From the 100% CPU consumption hint and its state as RUNNABLE, its evident its doing an infinite loop.

The code can go into infinite loop if and only if the nextQueue has a value that's already in the chain (or this). It could very well be an application problem. Thanks.

Methinks answered 15/7, 2015 at 12:37 Comment(1)
I never thought of this, but it is indeed possible the library I use does this EventQueue.push. It's not an open source library, so I'll have to check with them.Hysteria
W
0

Your problem is a deadlock problem(see wikipeida).

Deadlock situation here As you can see above, your two EventQueues (here R1 and R2) are in a deadlock situation - each of them has claimed one resource and cannot run further while the other one did claim the other resource. Both are waiting for each other endless.

You can solve this problem with different approaches:

Try to change the library, you're right that a library shouldn't try to do awt stuff if it is not a library closely related to awt. Thereare many libraries on platforms like github, I'm quite sure you find another library to replace your one which causes the error.

If you are able to edit your code to add monitoring you are preventing any deadlocks, too.

synchronized(lock){
EventQueue next = eq.nextQueue;
while (next != null) {
    eq = next;
    next = eq.nextQueue;
}
lock.notifyAll();
}
Waldgrave answered 11/7, 2015 at 12:12 Comment(1)
The code above is part of the Java SDK (java.awt.EventQueue.isDispatchThreadImpl(EventQueue.java:1024)), there is no way I can - or would want to - change that code.Hysteria

© 2022 - 2024 — McMap. All rights reserved.