United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6786210 Deadlock occurs when handling mouseLeave on XToolkit
JDK-6786210 : Deadlock occurs when handling mouseLeave on XToolkit

Details
Type:
Bug
Submit Date:
2008-12-17
Status:
Resolved
Updated Date:
2011-01-19
Project Name:
JDK
Resolved Date:
2009-01-14
Component:
client-libs
OS:
linux,generic
Sub-Component:
java.awt
CPU:
x86,generic
Priority:
P1
Resolution:
Fixed
Affected Versions:
6u10,6u12
Fixed Versions:
6u12 (b04)

Related Reports
Duplicate:
Duplicate:

Sub Tasks

Description
The problem is reported here: http://forums.java.net/jive/thread.jspa?messageID=322051

The stack trace of the deadlock:

Name: AWT-XAWT
State: BLOCKED on sun.awt.X11.XDialogPeer@25ec1ff7 owned by: AWT-EventQueue-1
Total blocked: 29 Total waited: 1,837

Stack trace: 
sun.awt.X11.XWindow.setMouseAbove(XWindow.java:789)
sun.awt.X11.XWindowPeer.setMouseAbove(XWindowPeer.java:1012)
sun.awt.X11.XWindow.leaveNotify(XWindow.java:799)
sun.awt.X11.XWindow.handleXCrossingEvent(XWindow.java:812)
sun.awt.X11.XWindowPeer.handleXCrossingEvent(XWindowPeer.java:1765)
sun.awt.X11.XBaseWindow.dispatchEvent(XBaseWindow.java:1119)
sun.awt.X11.XBaseWindow.dispatchToWindow(XBaseWindow.java:1079)
sun.awt.X11.XToolkit.dispatchEvent(XToolkit.java:475)
sun.awt.X11.XToolkit.run(XToolkit.java:588)
sun.awt.X11.XToolkit.run(XToolkit.java:523)
java.lang.Thread.run(Thread.java:619)

Name: AWT-EventQueue-1
State: WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@48f2d715 owned by: AWT-XAWT
Total blocked: 18,133 Total waited: 19,299

Stack trace: 
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:747)
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:778)
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1114)
java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
sun.awt.SunToolkit.awtLock(SunToolkit.java:241)
sun.awt.X11.XDropTargetRegistry.unregisterDropSite(XDropTargetRegistry.java:569)
sun.awt.X11.XWindowPeer.removeDropTarget(XWindowPeer.java:1634)
- locked sun.awt.X11.XDialogPeer@25ec1ff7
sun.awt.X11.XComponentPeer.removeDropTarget(XComponentPeer.java:1511)
java.awt.dnd.DropTarget.removeNotify(DropTarget.java:517)
java.awt.Component.removeNotify(Component.java:6721)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
java.awt.Container.removeNotify(Container.java:2611)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
org.openide.explorer.view.ListView$NbList.removeNotify(ListView.java:834)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
org.openide.explorer.view.ListView.removeNotify(ListView.java:607)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
javax.swing.JComponent.removeNotify(JComponent.java:4699)
javax.swing.JRootPane.removeNotify(JRootPane.java:750)
java.awt.Container.removeNotify(Container.java:2604)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
java.awt.Window.removeNotify(Window.java:685)
- locked java.awt.Component$AWTTreeLock@69d8ad6a
org.netbeans.core.windows.services.NbPresenter.removeNotify(NbPresenter.java:349)
java.awt.Window$1DisposeAction.run(Window.java:1013)
java.awt.Window.doDispose(Window.java:1025)
java.awt.Dialog.doDispose(Dialog.java:1248)
java.awt.Window.dispose(Window.java:972)
org.openide.explorer.propertysheet.PropertyDialogManager.actionPerformed(PropertyDialogManager.java:543)
org.netbeans.core.windows.services.NbPresenter$ButtonListener.actionPerformed(NbPresenter.java:1137)
javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
java.awt.Component.processMouseEvent(Component.java:6213)
javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
java.awt.Component.processEvent(Component.java:5978)
java.awt.Container.processEvent(Container.java:2036)
java.awt.Component.dispatchEventImpl(Component.java:4580)
java.awt.Container.dispatchEventImpl(Container.java:2094)
java.awt.Component.dispatchEvent(Component.java:4410)
java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4551)
java.awt.LightweightDispatcher.processMouseEvent(Container.java:4215)
java.awt.LightweightDispatcher.dispatchEvent(Container.java:4145)
java.awt.Container.dispatchEventImpl(Container.java:2080)
java.awt.Window.dispatchEventImpl(Window.java:2475)
java.awt.Component.dispatchEvent(Component.java:4410)
java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:104)
java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:178)
java.awt.Dialog$1.run(Dialog.java:1051)
java.awt.Dialog$3.run(Dialog.java:1103)
java.security.AccessController.doPrivileged(Native Method)
java.awt.Dialog.show(Dialog.java:1101)
org.netbeans.core.windows.services.NbPresenter.superShow(NbPresenter.java:867)
org.netbeans.core.windows.services.NbPresenter.doShow(NbPresenter.java:901)
org.netbeans.core.windows.services.NbPresenter.run(NbPresenter.java:889)
org.netbeans.core.windows.services.NbPresenter.run(NbPresenter.java:109)
org.openide.util.Mutex.doEventAccess(Mutex.java:1355)
org.openide.util.Mutex.readAccess(Mutex.java:268)
org.netbeans.core.windows.services.NbPresenter.show(NbPresenter.java:874)
java.awt.Component.show(Component.java:1513)
java.awt.Component.setVisible(Component.java:1465)
java.awt.Window.setVisible(Window.java:841)
java.awt.Dialog.setVisible(Dialog.java:991)
org.openide.explorer.propertysheet.CustomEditorAction.actionPerformed(CustomEditorAction.java:318)
org.openide.explorer.propertysheet.SheetTable.processMouseEvent(SheetTable.java:710)
java.awt.Component.processEvent(Component.java:5978)
java.awt.Container.processEvent(Container.java:2036)
java.awt.Component.dispatchEventImpl(Component.java:4580)
java.awt.Container.dispatchEventImpl(Container.java:2094)
java.awt.Component.dispatchEvent(Component.java:4410)
java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4551)
java.awt.LightweightDispatcher.processMouseEvent(Container.java:4212)
java.awt.LightweightDispatcher.dispatchEvent(Container.java:4145)
java.awt.Container.dispatchEventImpl(Container.java:2080)
java.awt.Window.dispatchEventImpl(Window.java:2475)
java.awt.Component.dispatchEvent(Component.java:4410)
java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:104)
java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

                                    

Comments
EVALUATION

This is a regression of 6730439 which introduced the method XWindow.setMouseAbove().

This method uses 'this' synchronization on the window peer object to synchronize access to the private boolean data field. However this is a bad practice since many other methods use 'this' synchronization in different cases. It may cause deadlocks under some circumstances, one of them is reported as this bug.

The methods (as well as the method isMouseAbove()) must be changed to use some private object for synchronization purposes.
                                     
2008-12-17
SUGGESTED FIX

--- old/src/solaris/classes/sun/awt/X11/XWindow.java	2008-12-22 17:20:38.000000000 +0300
+++ new/src/solaris/classes/sun/awt/X11/XWindow.java	2008-12-22 17:20:38.000000000 +0300
@@ -786,11 +786,19 @@
     native boolean haveCurrentX11InputMethodInstance();
 
     private boolean mouseAboveMe;
-    public synchronized boolean isMouseAbove() {
-        return mouseAboveMe;
+
+    // We consider peers non-serializable, hence the use of 'final'.
+    private final Object peerLock = new Object();
+
+    public boolean isMouseAbove() {
+        synchronized (peerLock) {
+            return mouseAboveMe;
+        }
     }
-    protected synchronized void setMouseAbove(boolean above) {
-        mouseAboveMe = above;
+    protected void setMouseAbove(boolean above) {
+        synchronized (peerLock) {
+            mouseAboveMe = above;
+        }
     }
 
     protected void enterNotify(long window) {
                                     
2008-12-22



Hardware and Software, Engineered to Work Together