This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 214872 - Deadlock involving NbStatusDisplayer, AWT-EventQueue-0, AWT-XAWT, XToolkt-Shutdown-Thread
Summary: Deadlock involving NbStatusDisplayer, AWT-EventQueue-0, AWT-XAWT, XToolkt-Shu...
Status: RESOLVED WONTFIX
Alias: None
Product: platform
Classification: Unclassified
Component: JDK Problems (show other bugs)
Version: 7.1.2
Hardware: PC Linux
: P3 normal (vote)
Assignee: Antonin Nebuzelsky
URL:
Keywords: JDK_SPECIFIC
: 223544 (view as bug list)
Depends on:
Blocks:
 
Reported: 2012-06-27 13:49 UTC by peterlevart
Modified: 2012-12-11 13:41 UTC (History)
2 users (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description peterlevart 2012-06-27 13:49:14 UTC
Deadlock has been detected at the startup of a Netbeans Platform application. It has been provoked by clicking on a menu when "Opening Main Window..." status has still been displayed in the status line. The deadlock also causes the whole Linux desktop to become unresponsive (events somehow don't get through to other apps as well). The environment is:

OS: Fedora 17 / 64 bit
JDK: Java 1.7.0_06-ea-b15
NB Platform: 7.1.2

There are 4 threads involved in the deadlock. Here are the stack traces obtained with jconcole deadlock detection button:


Name: XToolkt-Shutdown-Thread
State: WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@6d07b9c7 owned by: AWT-XAWT
Total blocked: 0  Total waited: 1

Stack trace: 
 sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834)
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:867)
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197)
java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214)
java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290)
sun.awt.SunToolkit.awtLock(SunToolkit.java:245)
sun.awt.X11.XAtom.<init>(XAtom.java:265)
sun.awt.X11.XAtom.<init>(XAtom.java:232)
sun.awt.X11.XAtom.get(XAtom.java:178)
sun.awt.X11.XSystemTrayPeer.<clinit>(XSystemTrayPeer.java:52)
sun.awt.X11.XToolkit$1$1.run(XToolkit.java:326)


Name: AWT-XAWT
State: BLOCKED on sun.awt.PostEventQueue@58a6f50a owned by: NbStatusDisplayer
Total blocked: 1  Total waited: 74

Stack trace: 
 sun.awt.PostEventQueue.postEvent(SunToolkit.java:2128)
sun.awt.SunToolkit.postEvent(SunToolkit.java:529)
sun.awt.X11.XWindow.postEvent(XWindow.java:429)
sun.awt.X11.XWindow.postEventToEventQueue(XWindow.java:440)
sun.awt.X11.XWindow.handleMotionNotify(XWindow.java:863)
sun.awt.X11.XWindowPeer.handleMotionNotify(XWindowPeer.java:2101)
sun.awt.X11.XBaseWindow.dispatchEvent(XBaseWindow.java:1096)
sun.awt.X11.XBaseWindow.dispatchToWindow(XBaseWindow.java:1066)
sun.awt.X11.XToolkit.dispatchEvent(XToolkit.java:565)
sun.awt.X11.XToolkit.run(XToolkit.java:674)
sun.awt.X11.XToolkit.run(XToolkit.java:595)
java.lang.Thread.run(Thread.java:722)


Name: NbStatusDisplayer
State: WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@19426a5e owned by: AWT-EventQueue-0
Total blocked: 7  Total waited: 5

Stack trace: 
 sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834)
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:867)
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197)
java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214)
java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290)
java.awt.EventQueue.postEventPrivate(EventQueue.java:235)
java.awt.EventQueue.postEvent(EventQueue.java:221)
sun.awt.PostEventQueue.flush(SunToolkit.java:2116)
   - locked sun.awt.PostEventQueue@58a6f50a
sun.awt.SunToolkit.flushPendingEvents(SunToolkit.java:563)
java.awt.EventQueue.postEvent(EventQueue.java:220)
java.awt.EventQueue.invokeLater(EventQueue.java:1188)
javax.swing.SwingUtilities.invokeLater(SwingUtilities.java:1287)
org.netbeans.core.windows.view.ui.StatusLine.stateChanged(StatusLine.java:95)
org.openide.util.ChangeSupport.fireChange(ChangeSupport.java:133)
org.openide.util.ChangeSupport.fireChange(ChangeSupport.java:119)
org.netbeans.core.NbStatusDisplayer.remove(NbStatusDisplayer.java:171)
org.netbeans.core.NbStatusDisplayer.access$300(NbStatusDisplayer.java:62)
org.netbeans.core.NbStatusDisplayer$MessageImpl.run(NbStatusDisplayer.java:197)
org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1411)
org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:1991)


Name: AWT-EventQueue-0
State: BLOCKED on sun.awt.PostEventQueue@58a6f50a owned by: NbStatusDisplayer
Total blocked: 15  Total waited: 264

Stack trace: 
 sun.awt.PostEventQueue.noEvents(SunToolkit.java:2104)
sun.awt.SunToolkit.isPostEventQueueEmpty(SunToolkit.java:577)
java.awt.EventQueue.detachDispatchThread(EventQueue.java:1048)
java.awt.EventDispatchThread.run(EventDispatchThread.java:103)
Comment 1 peterlevart 2012-06-27 14:16:06 UTC
I also managed to reproduce the deadlock using JDK 1.7.0_04. This time the dump has been obtained by sending QUIT signal to the JVM process and it says that only two threads are involved:

[INFO] Found one Java-level deadlock:
[INFO] =============================
[INFO] "NbStatusDisplayer":
[INFO]   waiting for ownable synchronizer 0x00000000e0624808, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
[INFO]   which is held by "AWT-EventQueue-0"
[INFO] "AWT-EventQueue-0":
[INFO]   waiting to lock monitor 0x00007fe3dc089d50 (object 0x00000000e0624960, a sun.awt.PostEventQueue),
[INFO]   which is held by "NbStatusDisplayer"
[INFO] 
[INFO] Java stack information for the threads listed above:
[INFO] ===================================================

[INFO] "NbStatusDisplayer":
[INFO]  at sun.misc.Unsafe.park(Native Method)
[INFO]  - parking to wait for  <0x00000000e0624808> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
[INFO]  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
[INFO]  at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834)
[INFO]  at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:867)
[INFO]  at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197)
[INFO]  at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214)
[INFO]  at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290)
[INFO]  at java.awt.EventQueue.postEventPrivate(EventQueue.java:235)
[INFO]  at java.awt.EventQueue.postEvent(EventQueue.java:221)
[INFO]  at sun.awt.PostEventQueue.flush(SunToolkit.java:2116)
[INFO]  - locked <0x00000000e0624960> (a sun.awt.PostEventQueue)
[INFO]  at sun.awt.SunToolkit.flushPendingEvents(SunToolkit.java:563)
[INFO]  at java.awt.EventQueue.postEvent(EventQueue.java:220)
[INFO]  at java.awt.EventQueue.invokeLater(EventQueue.java:1188)
[INFO]  at javax.swing.SwingUtilities.invokeLater(SwingUtilities.java:1287)
[INFO]  at org.netbeans.core.windows.view.ui.StatusLine.stateChanged(StatusLine.java:95)
[INFO]  at org.openide.util.ChangeSupport.fireChange(ChangeSupport.java:133)
[INFO]  at org.openide.util.ChangeSupport.fireChange(ChangeSupport.java:119)
[INFO]  at org.netbeans.core.NbStatusDisplayer.remove(NbStatusDisplayer.java:171)
[INFO]  at org.netbeans.core.NbStatusDisplayer.access$300(NbStatusDisplayer.java:62)
[INFO]  at org.netbeans.core.NbStatusDisplayer$MessageImpl.run(NbStatusDisplayer.java:197)
[INFO]  at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1411)
[INFO]  at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:1991)

[INFO] "AWT-EventQueue-0":
[INFO]  at sun.awt.PostEventQueue.noEvents(SunToolkit.java:2104)
[INFO]  - waiting to lock <0x00000000e0624960> (a sun.awt.PostEventQueue)
[INFO]  at sun.awt.SunToolkit.isPostEventQueueEmpty(SunToolkit.java:577)
[INFO]  at java.awt.EventQueue.detachDispatchThread(EventQueue.java:1048)
[INFO]  at java.awt.EventDispatchThread.run(EventDispatchThread.java:103)
[INFO] 
[INFO] Found 1 deadlock.
Comment 2 peterlevart 2012-06-27 14:23:18 UTC
I haven't been able to reproduce this on JDK 1.6.0_32 (yet)...
Comment 3 peterlevart 2012-06-28 06:48:13 UTC
I think that the root of the problem is in JDK 1.7, namely in the method:

java.awt.EventQueue.detachDispatchThread

...where it calls SunToolkit.isPostEventQueueEmpty() while holding global "pushPopLock".

The static method SunToolkit.isPostEventQueueEmpty() invokes a synchronized method on a singleton PostEventQueue object. Also other methods on this singleton PostEventQueue are synchronized and some of them (for example PostEventQueue.flush() invoked from static SunToolkit.flushPendingEvents()) are also synchronized and call into the java.awt.EventQueue which tries to get the global "pushPopLock" - hece the deadlock.

SunToolkit.isPostEventQueueEmpty() (or any of it's methods that delegate to PostEventQueue singleton) should not be called while holding global "pushPopLock" in java.awt.EventQueue...
Comment 4 peterlevart 2012-06-28 07:07:02 UTC
That's clearly a JDK bug (SunToolkit/AWT). While looking at the SunToolkit code I spoted another one: The following code:


    private static final Lock flushLock = new ReentrantLock();
    private static boolean isFlushingPendingEvents = false;

    /*
     * Flush any pending events which haven't been posted to the AWT
     * EventQueue yet.
     */
    public static void flushPendingEvents()  {
        flushLock.lock();
        try {
            // Don't call flushPendingEvents() recursively
            if (!isFlushingPendingEvents) {
                isFlushingPendingEvents = true;
                AppContext appContext = AppContext.getAppContext();
                PostEventQueue postEventQueue =
                    (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
                if (postEventQueue != null) {
                    postEventQueue.flush();
                }
            }
        } finally {
            isFlushingPendingEvents = false;
            flushLock.unlock();
        }
    }


... is clearly wrong. The isFlushingPendingEvents flag is reset in finally block regardless of whether it was true or false at the entry to the try block. The 1st nested call to flushPendingEvents() prevents recursion but it also resets the flag so that the second nested call is allowed...
Comment 5 peterlevart 2012-06-28 07:17:03 UTC
My proposal to fix this bug is to rewrite the SunToolkit.PostEventQueue to use the same global "pushPopLock" Lock instance that java.awt.EnetQueue uses for it's synchronization instead of "synchronized" instance methods...
Comment 6 peterlevart 2012-07-02 10:30:50 UTC
I submited 2 bug reports for JDK. Te 1st (deadlock involving a mutex Lock from java.awt.EventQueue and SunToolkit.PostEven) is Bug ID: 7181081, the 2nd (wrong logic to prevent recursion in SunToolkit.flushPendingEvents()) is Bug ID: 7181082.
Let's hope for quick response from JDK team...
Comment 7 Antonin Nebuzelsky 2012-07-13 13:59:21 UTC
Thanks for reporting to JDK. Closing this issue on our side as wontfix.
Comment 8 Milos Kleint 2012-12-11 13:41:40 UTC
*** Bug 223544 has been marked as a duplicate of this bug. ***