diff options
author | Sven Gothel <[email protected]> | 2015-07-27 20:05:09 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2015-07-27 20:05:09 +0200 |
commit | b0af5159bc6100a6262afe6b52f9092a207ac2b3 (patch) | |
tree | 8379e6a283fd3c5028889ef9ad0e96ed77c3c3c3 | |
parent | 6ae08be1742e6d805b316c0d440364854a49e68f (diff) |
Bug 1181 - JOGL WebStart Applications using GLCanvas/AWT may Deadlock by two AWT-EDT on Java >= 1.8.0_45
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(),
where Component.getGraphicsConfiguration() is being used to
detect possible reconfiguration.
- Also use updated AWTGraphicsConfiguration's GraphicsConfiguration
if no 'new' detection is required.
5 files changed, 54 insertions, 26 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java index 3a8cbefc6..3eece0759 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java @@ -340,9 +340,10 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, /** * Updates bounds and pixelScale + * @param gc GraphicsConfiguration for {@link #updatePixelScale(GraphicsConfiguration, boolean)} * @return true if bounds or pixelScale has changed, otherwise false */ - protected final boolean updateLockedData(final JAWT_Rectangle jawtBounds) { + protected final boolean updateLockedData(final JAWT_Rectangle jawtBounds, final GraphicsConfiguration gc) { final Rectangle jb = new Rectangle(jawtBounds.getX(), jawtBounds.getY(), jawtBounds.getWidth(), jawtBounds.getHeight()); final boolean changedBounds = !bounds.equals(jb); @@ -358,29 +359,31 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } } - updatePixelScale(false); + updatePixelScale(gc, false); return hasPixelScaleChanged || changedBounds; } /** * Updates the minimum and maximum pixel-scale values * and returns {@code true} if they were updated. + * @param gc pre-fetched {@link GraphicsConfiguration} instance of {@link #getAWTComponent() upstream component}, + * caller may use cached {@link #getAWTGraphicsConfiguration()}'s {@link AWTGraphicsConfiguration#getAWTGraphicsConfiguration() GC} + * or a {@link Component#getGraphicsConfiguration()}. * @param clearFlag if {@code true}, the {@code hasPixelScaleChanged} flag will be cleared * @return {@code true} if values were updated, otherwise {@code false}. * @see #hasPixelScaleChanged() + * @see #getAWTGraphicsConfiguration() + * @see Component#getGraphicsConfiguration() */ - public final boolean updatePixelScale(final boolean clearFlag) { - // Using GraphicsConfiguration from component, which may change by moving to diff monitor - if( EventQueue.isDispatchThread() || Thread.holdsLock(component.getTreeLock()) ) { - if( JAWTUtil.getPixelScale(component.getGraphicsConfiguration(), minPixelScale, maxPixelScale) ) { - hasPixelScaleChanged = true; - if( DEBUG ) { - System.err.println("JAWTWindow.updatePixelScale: updated req["+ - reqPixelScale[0]+", "+reqPixelScale[1]+"], min["+ - minPixelScale[0]+", "+minPixelScale[1]+"], max["+ - maxPixelScale[0]+", "+maxPixelScale[1]+"], has["+ - hasPixelScale[0]+", "+hasPixelScale[1]+"]"); - } + public final boolean updatePixelScale(final GraphicsConfiguration gc, final boolean clearFlag) { + if( JAWTUtil.getPixelScale(gc, minPixelScale, maxPixelScale) ) { + hasPixelScaleChanged = true; + if( DEBUG ) { + System.err.println("JAWTWindow.updatePixelScale: updated req["+ + reqPixelScale[0]+", "+reqPixelScale[1]+"], min["+ + minPixelScale[0]+", "+minPixelScale[1]+"], max["+ + maxPixelScale[0]+", "+maxPixelScale[1]+"], has["+ + hasPixelScale[0]+", "+hasPixelScale[1]+"]"); } } if( clearFlag ) { @@ -391,6 +394,12 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, return hasPixelScaleChanged; } } + /** + * @deprecated Use {@link #updatePixelScale(GraphicsConfiguration, boolean)}. + */ + public final boolean updatePixelScale(final boolean clearFlag) { + return updatePixelScale(awtConfig.getAWTGraphicsConfiguration(), clearFlag); + } /** * Returns and clears the {@code hasPixelScaleChanged} flag, as set via {@link #lockSurface()}. @@ -414,7 +423,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, * @return true if pixelScale has changed, otherwise false */ protected final boolean setReqPixelScale() { - updatePixelScale(true); + updatePixelScale(awtConfig.getAWTGraphicsConfiguration(), true); return SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG ? getClass().getSimpleName() : null); } @@ -619,7 +628,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, * @throws NativeWindowException */ protected abstract JAWT fetchJAWTImpl() throws NativeWindowException; - protected abstract int lockSurfaceImpl() throws NativeWindowException; + protected abstract int lockSurfaceImpl(GraphicsConfiguration gc) throws NativeWindowException; protected void dumpJAWTInfo() { System.err.println(jawt2String(null).toString()); @@ -640,6 +649,19 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, ExceptionUtils.dumpStack(System.err); } } else { + final GraphicsConfiguration gc; + if( EventQueue.isDispatchThread() || Thread.holdsLock(component.getTreeLock()) ) { + /** + * Trigger detection of possible reconfiguration before 'sun.awt.SunToolkit.awtLock()', + * which maybe triggered via adevice.lock() below (X11). + * See setAWTGraphicsConfiguration(..). + */ + gc = component.getGraphicsConfiguration(); + } else { + // Reuse cached instance + gc = awtConfig.getAWTGraphicsConfiguration(); + } + determineIfApplet(); try { final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); @@ -649,7 +671,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, jawt = fetchJAWTImpl(); isOffscreenLayerSurface = JAWTUtil.isJAWTUsingOffscreenLayer(jawt); } - res = lockSurfaceImpl(); + res = lockSurfaceImpl(gc); if(LOCK_SUCCESS == res && drawable_old != drawable) { res = LOCK_SURFACE_CHANGED; if(DEBUG) { diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java index 6f3f1ed6b..264bdf9d3 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java @@ -41,6 +41,7 @@ package jogamp.nativewindow.jawt.macosx; import java.awt.Component; +import java.awt.GraphicsConfiguration; import java.nio.Buffer; import java.security.AccessController; import java.security.PrivilegedAction; @@ -242,7 +243,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { } @Override - protected int lockSurfaceImpl() throws NativeWindowException { + protected int lockSurfaceImpl(final GraphicsConfiguration gc) throws NativeWindowException { int ret = NativeSurface.LOCK_SURFACE_NOT_READY; ds = getJAWT().GetDrawingSurface(component); if (ds == null) { @@ -279,7 +280,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { unlockSurfaceImpl(); return NativeSurface.LOCK_SURFACE_NOT_READY; } - updateLockedData(dsi.getBounds()); + updateLockedData(dsi.getBounds(), gc); if (DEBUG && firstLock ) { dumpInfo(); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java index a6c9452af..655dadd6b 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java @@ -40,6 +40,8 @@ package jogamp.nativewindow.jawt.windows; +import java.awt.GraphicsConfiguration; + import com.jogamp.nativewindow.AbstractGraphicsConfiguration; import com.jogamp.nativewindow.NativeSurface; import com.jogamp.nativewindow.NativeWindow; @@ -72,7 +74,7 @@ public class WindowsJAWTWindow extends JAWTWindow { } @Override - protected int lockSurfaceImpl() throws NativeWindowException { + protected int lockSurfaceImpl(final GraphicsConfiguration gc) throws NativeWindowException { int ret = NativeSurface.LOCK_SUCCESS; ds = getJAWT().GetDrawingSurface(component); if (ds == null) { @@ -99,7 +101,7 @@ public class WindowsJAWTWindow extends JAWTWindow { unlockSurfaceImpl(); return LOCK_SURFACE_NOT_READY; } - updateLockedData(dsi.getBounds()); + updateLockedData(dsi.getBounds(), gc); win32dsi = (JAWT_Win32DrawingSurfaceInfo) dsi.platformInfo(getJAWT()); if (win32dsi == null) { unlockSurfaceImpl(); diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java index 2620b60e0..80cf3ba6f 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java @@ -37,6 +37,8 @@ package jogamp.nativewindow.jawt.x11; +import java.awt.GraphicsConfiguration; + import com.jogamp.nativewindow.AbstractGraphicsConfiguration; import com.jogamp.nativewindow.NativeSurface; import com.jogamp.nativewindow.NativeWindow; @@ -67,7 +69,7 @@ public class X11JAWTWindow extends JAWTWindow { } @Override - protected int lockSurfaceImpl() throws NativeWindowException { + protected int lockSurfaceImpl(final GraphicsConfiguration gc) throws NativeWindowException { int ret = NativeSurface.LOCK_SUCCESS; ds = getJAWT().GetDrawingSurface(component); if (ds == null) { @@ -94,7 +96,7 @@ public class X11JAWTWindow extends JAWTWindow { unlockSurfaceImpl(); return LOCK_SURFACE_NOT_READY; } - updateLockedData(dsi.getBounds()); + updateLockedData(dsi.getBounds(), gc); x11dsi = (JAWT_X11DrawingSurfaceInfo) dsi.platformInfo(getJAWT()); if (x11dsi == null) { unlockSurfaceImpl(); diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 0a27f7f22..ae32fd164 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -626,8 +626,8 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } } } - private final boolean updatePixelScale() { - if( jawtWindow.updatePixelScale(true) ) { + private final boolean updatePixelScale(final GraphicsConfiguration gc) { + if( jawtWindow.updatePixelScale(gc, true) ) { final Window cWin = newtChild; final Window dWin = cWin.getDelegatedWindow(); if( dWin instanceof WindowImpl ) { @@ -718,6 +718,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } else { NewtFactoryAWT.destroyNativeWindow(jawtWindow); jawtWindow=null; + awtConfig=null; destroyJAWTPending = false; } } @@ -747,7 +748,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto System.err.println("NewtCanvasAWT.reshape: "+x+"/"+y+" "+width+"x"+height); } if( validateComponent(true) ) { - if( !printActive && updatePixelScale() ) { + if( !printActive && updatePixelScale(getGraphicsConfiguration()) ) { // NOP } else { // newtChild.setSize(width, height); |