Bug 1181

Summary: JOGL WebStart Applications using GLCanvas/AWT may Deadlock by two AWT-EDT on Java >= 1.8.0_45
Product: [JogAmp] Jogl Reporter: Sven Gothel <sgothel>
Component: awtAssignee: Sven Gothel <sgothel>
Status: RESOLVED FIXED    
Severity: major    
Priority: P2    
Version: 2.3.2   
Hardware: pc_all   
OS: linux   
Type: DEFECT SCM Refs:
b0af5159bc6100a6262afe6b52f9092a207ac2b3
Workaround: ---
Bug Depends on: 1184    
Bug Blocks:    

Description Sven Gothel 2015-07-26 04:45:03 CEST
Platform GNU/Linux X11
Java: 1.8.0_45 and 1.8.0_51

Deadlock appears to happen at launch via WebStart on X11
due to _two_ AWT-EDT holding the AWT tree lock.

The final deadlocked call comes from JOGL's JAWTWindow
issuing GLCanvas/AWT's Component.getGraphicsConfiguration(..).

+++

"AWT-EventQueue-2":
        at java.awt.Component.getGraphicsConfiguration(Component.java:1145)
        - waiting to lock <0x00000006c6204248> (a java.awt.Component$AWTTreeLock)
        at com.jogamp.opengl.awt.GLCanvas.getGraphicsConfiguration(GLCanvas.java:351)
        at com.jogamp.nativewindow.awt.JAWTWindow.updatePixelScale(JAWTWindow.java:347)
        at com.jogamp.nativewindow.awt.JAWTWindow.updateLockedData(JAWTWindow.java:333)
        at jogamp.nativewindow.jawt.x11.X11JAWTWindow.lockSurfaceImpl(X11JAWTWindow.java:97)
        at com.jogamp.nativewindow.awt.JAWTWindow.lockSurface(JAWTWindow.java:624)
        at jogamp.opengl.GLDrawableImpl.lockSurface(GLDrawableImpl.java:315)
        at jogamp.opengl.GLContextImpl.makeCurrent(GLContextImpl.java:596)
        at jogamp.opengl.GLContextImpl.makeCurrent(GLContextImpl.java:580)
        at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1263)
        at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1131)
        at com.jogamp.opengl.awt.GLCanvas$12.run(GLCanvas.java:1435)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:301)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
        at java.awt.EventQueue.access$500(EventQueue.java:97)
        at java.awt.EventQueue$3.run(EventQueue.java:709)
        at java.awt.EventQueue$3.run(EventQueue.java:703)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
"AWT-EventQueue-1":
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000006c64ba3f8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)
        at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)
        at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)
        at sun.awt.SunToolkit.awtLock(SunToolkit.java:253)
        at sun.font.XRTextRenderer.drawGlyphList(XRTextRenderer.java:63)
        at sun.java2d.pipe.GlyphListPipe.drawChars(GlyphListPipe.java:104)
        at sun.java2d.SunGraphics2D.drawChars(SunGraphics2D.java:3036)
        at sun.swing.SwingUtilities2.drawChars(SwingUtilities2.java:857)
        at javax.swing.text.Utilities.drawTabbedText(Utilities.java:176)
        at javax.swing.text.Utilities.drawTabbedText(Utilities.java:106)
        at javax.swing.text.PlainView.drawUnselectedText(PlainView.java:154)
        at javax.swing.text.PlainView.drawElement(PlainView.java:113)
        at javax.swing.text.PlainView.drawLine(PlainView.java:82)
        at javax.swing.text.PlainView.paint(PlainView.java:311)
        at javax.swing.plaf.basic.BasicTextUI$RootView.paint(BasicTextUI.java:1434)
        at javax.swing.plaf.basic.BasicTextUI.paintSafely(BasicTextUI.java:737)
        at javax.swing.plaf.basic.BasicTextUI.paint(BasicTextUI.java:881)
        at javax.swing.plaf.basic.BasicTextUI.update(BasicTextUI.java:860)
        at javax.swing.JComponent.paintComponent(JComponent.java:780)
        at javax.swing.JComponent.paint(JComponent.java:1056)
        at javax.swing.JComponent.paintChildren(JComponent.java:889)
        - locked <0x00000006c6204248> (a java.awt.Component$AWTTreeLock)
        at javax.swing.JComponent.paint(JComponent.java:1065)
        at javax.swing.JViewport.paint(JViewport.java:728)
        at javax.swing.JComponent.paintChildren(JComponent.java:889)
        - locked <0x00000006c6204248> (a java.awt.Component$AWTTreeLock)
        at javax.swing.JComponent.paint(JComponent.java:1065)
        at javax.swing.JComponent.paintToOffscreen(JComponent.java:5219)
        at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:290)
        at javax.swing.RepaintManager.paint(RepaintManager.java:1265)
        at javax.swing.JComponent._paintImmediately(JComponent.java:5167)
        at javax.swing.JComponent.paintImmediately(JComponent.java:4978)
        at javax.swing.RepaintManager$4.run(RepaintManager.java:824)
        at javax.swing.RepaintManager$4.run(RepaintManager.java:807)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:807)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:782)
        at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:731)
Comment 1 Sven Gothel 2015-07-26 05:18:39 CEST
Found one Java-level deadlock:
=============================
"AWT-EventQueue-2":
  waiting to lock monitor 0x00007fca300048a8 (object 0x00000006c6204248, a java.awt.Component$AWTTreeLock),
  which is held by "AWT-EventQueue-1"

^^ JAWTWindow trying to get monitor AWT-TreeLock,
but holds lock SunToolkit.awtLock (0x00000006c64ba3f8), see below.

++

"AWT-EventQueue-1":
  waiting for ownable synchronizer 0x00000006c64ba3f8, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
  which is held by "AWT-EventQueue-2"

Trying to acquire lock SunToolkit.awtLock (0x00000006c64ba3f8),
but holds monitor AWT-TreeLock (0x00007fca300048a8).
Comment 2 Sven Gothel 2015-07-27 20:01:55 CEST
Root cause:

- AWT Toolkit global Lock

Our locking scheme (AWT-EDT-1):
- Surface Lock
- sun.awt.SunToolkit.awtLock()
- Component.getGraphicsConfiguration() -> synchronized(Component.getTreeLock())

Other AWT-EDT-2 by Webstart:
- synchronized(Component.getTreeLock())
- sun.awt.SunToolkit.awtLock()

Results in a deadlock.

Solution:
 - Issue Component.getGraphicsConfiguration() before awtLock()

+++

Further code analysis
Comment 3 Sven Gothel 2015-07-27 20:05:38 CEST
commit b0af5159bc6100a6262afe6b52f9092a207ac2b3

     - Issue Component.getGraphicsConfiguration() before awtLock(),
       where Component.getGraphicsConfiguration() is being used to
       detect possible reconfiguration.
    
     - Also use updated AWTGraphicsConfiguration's GraphicsConfiguration
       if no 'new' detection is required.