JDK-8001463 : Regression : Deadlock between AWT-XAWT thread and AWT-EventQueue-0 Thread when screen resolution changes
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 8
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: other
  • Submitted: 2012-10-24
  • Updated: 2014-12-11
  • Resolved: 2013-10-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8 b112Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
SYNOPSIS
--------
Regression : Deadlock between AWT-XAWT thread and AWT-EventQueue-0 Thread when screen resolution changes

OPERATING SYSTEM
----------------
Linux

FULL JDK VERSION
----------------
Java 8 b17 onwards

PROBLEM DESCRIPTION from LICENSEE
---------------------------------
The RFE for 7045370 means that Java 8 can detect screen resolution changes and update its display with new resolution (screen width and height).

While testing this feature, we observe that occasionally a Java application GUI  with the focus becomes non-responsive soon after a screen resolution change. The deadlock occurs between the AWT-XAWT event dispatch thread and the AWT-EventQueue-0 event dispatch thread. Another customer has reported a deadlock between same threads but a slightly different scenario (CR 7105941) - it seems unlikely, but this issue may or may not be related.

When a screen resolution change occurs, X11 seems to dispatch 2 XConfigureNotify events. The first one is for the current resolution, and the second for the new resolution. We have analysed this in detail, and we found that the problem seems to occur when there is a delay with the second XConfigureNotify event, with other X11 events (XVisibilityNotify and XExpose) occurring in between.

The result of that scenario is that the AWT-EventQueue-0 thread will issue a repaint event and in order to do that it grabs the AWTTreeLock. Meanwhile, the second XConfigureNotify event dispatch occurs and the  AWT-XAWT thread grabs the toolkit AWT lock (ReentrantLock). AWT-XAWT then requires the the AWTTreeLock to grab the current window's GraphicsConfiguration, while AWT-EventQueue-0 requires the toolkit AWT lock to render the repainted image into the X11 surface. The result is a classic deadlock.

In the passing case, two XConfigureNotify events occur in a close timing window with no XVisibilityNotify and XExpose in between. No repaint is triggered between the two events and no deadlock occurs.

As AWT-EventQueue-0 and AWT-XAWT shares locks there is always a chance to get into a deadlock scenario if a particular lock sequence is breached. As explained there are different scenario for these thread to get into a deadlock state (7105941).

REPRODUCTION INSTRUCTIONS
-------------------------
The problem is re-creatable with the Java 2D demo.  The problem seems to be more re-creatable when the resolution is reduced from a higher value to next lower value (e.g. change resolution from x=1600, y=900 to x=1440, y=900 ). The issue is rarely seen when the resolution is changed from a lower value to a higher value. It also may take up to several test runs or minimizes back and forth to manifest the hang.

1. java -jar /jdk1.8.0/demo/jfc/Java2D/Java2Demo.jar
2. Change screen resolution
3. Java 2D demo will be seen in hung state.

WORKAROUND
----------
If the application is minimized while the resolution is changed the deadlock does not occur.

Comments
Verified in JDK8b116 Oracle linux 6.4 x32 Test api/java_awt/GraphicsDevice/indexTGF.html#SetDisplayMode passed successfully
21-11-2013

Regarding " i.e. that XVisibilityNotify / XExpose can lead to a Java layer repaint?" - well, XExpose is the repaint event in X11, so it is natural that it gets translated to a Java paint event. However, I'm not sure if postponing/delaying any events makes sense. As I indicated earlier (see a comment from 2012-12-24) we should try and reduce the time while the AWTLock is held, wrapping only necessary calls with that lock. This idea needs to be implemented and tested.
23-04-2013

Based on the stack trace above I think we could try to temporarily release the AWTLock when dispatching the VSM.displayChanged()/SVI.updateGraphicsConfig() calls or even earlier on the stack, since the processing of these events does not need to call X11 routines and as such doesn't require the AWTLock.
24-12-2012

For me it sounds like a good solution. The only things we should take into account are screen devices list and display changed implementation. 1. I am not sure whether we can use getScreenDevices() without awtLock here, but it seems nothing wrong can happen. The only native data here is a number of screens which is used to create new GraphicsDevice instances. 2. DisplayChangedListener.displayChanged has quite many implementations including WGLGraphicsConfig class. As far as awtLock is intended to guard X11 and OpenGl native calls, I am not sure that displayChanged can be invoked without synchronization.
24-12-2012

Denis, I just attached a stack to the report. I was able to reproduce as follows: OpenSuse 11.4 JDK8-b67 JDK7u10 Java2D Demo as indicated in the report. Cycle between highest and lowest resolutation about 10 times (be sure to *accept* the resolution each time you switch). Found one Java-level deadlock: ============================= "AWT-EventQueue-0": waiting for ownable synchronizer 0x00000000d6ff56d0, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), which is held by "AWT-XAWT" "AWT-XAWT": waiting to lock monitor 0x0000000000d89b58 (object 0x00000000d6f81c48, a java.awt.Component$AWTTreeLock), which is held by "AWT-EventQueue-0" Java stack information for the threads listed above: =================================================== "AWT-EventQueue-0": at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00000000d6ff56d0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) 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:868) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:211) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:287) at sun.awt.SunToolkit.awtLock(SunToolkit.java:239) at sun.java2d.xr.XRRenderer.drawLine(XRRenderer.java:83) at sun.java2d.SunGraphics2D.drawLine(SunGraphics2D.java:2141) at javax.swing.plaf.metal.MetalTabbedPaneUI.paintTopTabBorder(MetalTabbedPaneUI.java:253) at javax.swing.plaf.metal.MetalTabbedPaneUI.paintTabBorder(MetalTabbedPaneUI.java:114) at javax.swing.plaf.basic.BasicTabbedPaneUI.paintTab(BasicTabbedPaneUI.java:859) at javax.swing.plaf.basic.BasicTabbedPaneUI.paintTabArea(BasicTabbedPaneUI.java:835) at javax.swing.plaf.basic.BasicTabbedPaneUI.paint(BasicTabbedPaneUI.java:797) at javax.swing.plaf.metal.MetalTabbedPaneUI.paint(MetalTabbedPaneUI.java:843) at javax.swing.plaf.metal.MetalTabbedPaneUI.update(MetalTabbedPaneUI.java:724) at javax.swing.JComponent.paintComponent(JComponent.java:778) at javax.swing.JComponent.paint(JComponent.java:1054) at javax.swing.JComponent.paintChildren(JComponent.java:887) - locked <0x00000000d6f81c48> (a java.awt.Component$AWTTreeLock) at javax.swing.JComponent.paint(JComponent.java:1063) at javax.swing.JComponent.paintChildren(JComponent.java:887) - locked <0x00000000d6f81c48> (a java.awt.Component$AWTTreeLock) at javax.swing.JComponent.paint(JComponent.java:1063) at javax.swing.JComponent.paintChildren(JComponent.java:887) - locked <0x00000000d6f81c48> (a java.awt.Component$AWTTreeLock) at javax.swing.JComponent.paint(JComponent.java:1063) at javax.swing.JLayeredPane.paint(JLayeredPane.java:586) at javax.swing.JComponent.paintChildren(JComponent.java:887) - locked <0x00000000d6f81c48> (a java.awt.Component$AWTTreeLock) at javax.swing.JComponent.paintToOffscreen(JComponent.java:5233) at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:290) at javax.swing.RepaintManager.paint(RepaintManager.java:1223) at javax.swing.JComponent.paint(JComponent.java:1040) at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39) at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79) at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116) at java.awt.Container.paint(Container.java:1968) at java.awt.Window.paint(Window.java:3877) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:797) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:740) at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:689) at javax.swing.RepaintManager.access$800(RepaintManager.java:59) at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1655) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:720) at java.awt.EventQueue.access$200(EventQueue.java:103) at java.awt.EventQueue$3.run(EventQueue.java:681) at java.awt.EventQueue$3.run(EventQueue.java:679) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) at java.awt.EventQueue.dispatchEvent(EventQueue.java:690) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139) at java.awt.EventDispatchThread.run(EventDispatchThread.java:97) "AWT-XAWT": at java.awt.Component.getGraphicsConfiguration(Component.java:1142) - waiting to lock <0x00000000d6f81c48> (a java.awt.Component$AWTTreeLock) at sun.awt.image.SunVolatileImage.updateGraphicsConfig(SunVolatileImage.java:138) at sun.awt.image.VolatileSurfaceManager.displayChanged(VolatileSurfaceManager.java:345) at sun.awt.SunDisplayChanger.notifyListeners(SunDisplayChanger.java:132) at sun.java2d.SunGraphicsEnvironment.displayChanged(SunGraphicsEnvironment.java:281) at sun.awt.X11.XToolkit$1.dispatchEvent(XToolkit.java:319) at sun.awt.X11.XToolkit.dispatchEvent(XToolkit.java:589) at sun.awt.X11.XToolkit.run(XToolkit.java:684) at sun.awt.X11.XToolkit.run(XToolkit.java:605) at java.lang.Thread.run(Thread.java:722) Found 1 deadlock.
21-12-2012

JLE was able to reproduce the deadlock and capture the stack.
21-12-2012

I cannot understand what window manager is used to reproduce the problem. As I understand the system is Suse. Thank you.
19-12-2012

-- From Licensee ------ We too struggled to reproduce the issue initially. The problem seems to be more re-creatable when the resolution is reduced from a higher value to next lower value (e.g. change resolution from x=1600, y=900 to x=1440, y=900 ). The issue is rarely seen when the resolution is changed from a lower value to a higher value. Also, these are the X versions with which we re-created the issue more frequently 1) X -version X.Org X Server 1.10.6 Release Date: 2012-02-10 X Protocol Version 11, Revision 0 Build Operating System: x86-007 2.6.18-308.1.1.el5 Current Operating System: Linux oc1622510553.ibm.com 2.6.32-279.9.1.el6.x86_64 #1 SMP Mon Oct 1 18:05:29 EDT 2012 x86_64 Kernel command line: ro root=/dev/mapper/vg_oc8026223766-lv_root rd_LVM_LV=vg_oc8026223766/lv_root exec-shield=1 selinux=1 rhgb quiet drm_kms_helper.poll=0 LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 rd_LVM_LV=vg_oc8026223766/lv_swap rd_LUKS_UUID=luks-a43a5602-4047-4805-9c54-0fb6f5c66e02 KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet crashkernel=129M@0M Build Date: 28 March 2012 03:02:14PM Build ID: xorg-x11-server 1.10.6-1.el6 Current version of pixman: 0.18.4 2) X -version X.Org X Server 1.6.5 Release Date: 2009-10-11 X Protocol Version 11, Revision 0 Build Operating System: openSUSE SUSE LINUX Current Operating System: Linux rttest1 2.6.33.18-rt31-0.3-rt #1 SMP PREEMPT RT 2011-08-26 11:51:57 +0200 x86_64 Build Date: 09 May 2010 12:50:35PM 3) X -version X Window System Version 7.1.1 Release Date: 12 May 2006 X Protocol Version 11, Revision 0, Release 7.1.1 Build Operating System: Linux 2.6.9-67.0.7.ELsmp x86_64 Red Hat, Inc. Current Operating System: Linux rttest2.in.ibm.com 2.6.24.7-108ibmrt2.1.17 #1 SMP PREEMPT RT Thu Aug 25 15:27:44 EDT 2011 x86_64 Build Date: 02 April 2008 Build ID: xorg-x11-server 1.1.1-48.41.el5 --------
18-12-2012

I cannot reproduce the problem on my dual screen Ubuntu 10.4 configuration. I use Unity. I see that the problem is not related to a particular Window Manager, but to make easy to reproduce the problem it would be better to get more info. Please specify which version of linux is used, which window manager. Even more important to get your stack trace dump. Please get it (for instance using ctrl + | ) and attach it to the request.
17-12-2012