diff options
author | Sven Gothel <[email protected]> | 2012-09-07 08:13:06 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-09-07 08:13:06 +0200 |
commit | f2cfb6119a3663715ed2d572643949b3bef58662 (patch) | |
tree | 7a31217a343c16e81549fab8beed1a1012e13156 /src/jogl | |
parent | ffcfd35929407c75308ab41883463bc8c8a89b91 (diff) |
Cleanup shutdown mechanism ; Fix X11/ATI SIGV at shutdown ; EGLDisplayUtil: Check for leaked display handles
GLProfile / all shutdown methods: Remove ShutdownType to remove complexity (not required)
Proper shutdown sequence:
GLProfile - GLDrawableFactory+ - GLContext - NativeWindowFactory - [X11Util, OSXUtil, ..]
GLDrawableFactory: Always keep shutdown-hook alive, required for X11Util shutdown (@ JVMShutdown only)
X11Util: Shutdown
- @ JVMShutdown only
- If GL vendor ATI: close pending X11 display connections in proper order of creation.
This finally removes the SIGV when shutting down the JVM on X11 w/ ATI driver.
EGLDisplayUtil: Add shutdown, allowing to validate whether leaked EGL display handles remain.
Diffstat (limited to 'src/jogl')
7 files changed, 75 insertions, 84 deletions
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index acda45bff..9fd895c1f 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -55,7 +55,6 @@ import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; -import javax.media.opengl.GLProfile.ShutdownType; import jogamp.opengl.Debug; @@ -106,6 +105,7 @@ public abstract class GLDrawableFactory { // Shutdown hook mechanism for the factory private static boolean factoryShutdownHookRegistered = false; private static Thread factoryShutdownHook = null; + private static volatile boolean isJVMShuttingDown = false; /** * Instantiate singleton factories if available, EGLES1, EGLES2 and the OS native ones. @@ -176,21 +176,24 @@ public abstract class GLDrawableFactory { } } - protected static void shutdown(ShutdownType shutdownType) { + protected static void shutdown() { if (isInit) { // volatile: ok synchronized (GLDrawableFactory.class) { if (isInit) { isInit=false; - unregisterFactoryShutdownHook(); - shutdownImpl(shutdownType); + shutdownImpl(); } } } } - private static void shutdownImpl(ShutdownType shutdownType) { + + private static void shutdownImpl() { + // Following code will _always_ remain in shutdown hook + // due to special semantics of native utils, i.e. X11Utils. + // The latter requires shutdown at JVM-Shutdown only. synchronized(glDrawableFactories) { for(int i=0; i<glDrawableFactories.size(); i++) { - glDrawableFactories.get(i).destroy(shutdownType); + glDrawableFactories.get(i).destroy(); } glDrawableFactories.clear(); @@ -198,6 +201,8 @@ public abstract class GLDrawableFactory { nativeOSFactory = null; eglFactory = null; } + GLContext.shutdown(); + NativeWindowFactory.shutdown(isJVMShuttingDown); } private static synchronized void registerFactoryShutdownHook() { @@ -206,7 +211,8 @@ public abstract class GLDrawableFactory { } factoryShutdownHook = new Thread(new Runnable() { public void run() { - GLDrawableFactory.shutdownImpl(GLProfile.ShutdownType.COMPLETE); + isJVMShuttingDown = true; + GLDrawableFactory.shutdownImpl(); } }); AccessController.doPrivileged(new PrivilegedAction<Object>() { @@ -218,20 +224,6 @@ public abstract class GLDrawableFactory { factoryShutdownHookRegistered = true; } - private static synchronized void unregisterFactoryShutdownHook() { - if (!factoryShutdownHookRegistered) { - return; - } - AccessController.doPrivileged(new PrivilegedAction<Object>() { - public Object run() { - Runtime.getRuntime().removeShutdownHook(factoryShutdownHook); - return null; - } - }); - factoryShutdownHookRegistered = false; - } - - protected GLDrawableFactory() { synchronized(glDrawableFactories) { glDrawableFactories.add(this); @@ -244,7 +236,7 @@ public abstract class GLDrawableFactory { protected void enterThreadCriticalZone() {}; protected void leaveThreadCriticalZone() {}; - protected abstract void destroy(ShutdownType shutdownType); + protected abstract void destroy(); /** * Retrieve the default <code>device</code> {@link AbstractGraphicsDevice#getConnection() connection}, diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index 513ccd101..23d789afd 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -198,44 +198,25 @@ public class GLProfile { getProfileMap(device, true); } - /** - * Shutdown type for {@link GLProfile#shutdown(ShutdownType)}. - * <p> - * {@link #SHARED_ONLY} For thread based resources only, suitable for eg. {@link java.applet.Applet Applet} restart.<br> - * {@link #COMPLETE} Everything.<br> - * </p> - */ - public enum ShutdownType { - /* Shared thread based resources only, eg. for Applets */ - SHARED_ONLY, - /* Everything */ - COMPLETE; - } - /** * Manual shutdown method, may be called after your last JOGL use * within the running JVM.<br> * It releases all temporary created resources, ie issues {@link javax.media.opengl.GLDrawableFactory#shutdown()}.<br> * The shutdown implementation is called via the JVM shutdown hook, if not manually invoked.<br> * <p> - * This method shall not need to be called for other reasons than issuing a proper shutdown of resources. + * This method shall not need to be called for other reasons than issuing a proper shutdown of resources at a defined time. * </p> - * @param type the shutdown type, see {@link ShutdownType}. */ - public static void shutdown(ShutdownType type) { + public static void shutdown() { initLock.lock(); try { if(initialized) { // volatile: ok initialized = false; if(DEBUG) { - System.err.println("GLProfile.shutdown(type: "+type+") - thread "+Thread.currentThread().getName()); + System.err.println("GLProfile.shutdown() - thread "+Thread.currentThread().getName()); Thread.dumpStack(); } - GLDrawableFactory.shutdown(type); - if(ShutdownType.COMPLETE == type) { - GLContext.shutdown(); - } - NativeWindowFactory.shutdown(); + GLDrawableFactory.shutdown(); } } finally { initLock.unlock(); @@ -1480,7 +1461,7 @@ public class GLProfile { if(DEBUG) { System.err.println("Info: GLProfile.init - EGL/ES2 ANGLE disabled"); } - eglFactory.destroy(ShutdownType.COMPLETE); + eglFactory.destroy(); eglFactory = null; hasEGLFactory = false; } else { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java index 18d2f830d..ce2e824f5 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java @@ -29,6 +29,7 @@ package jogamp.opengl.egl; import java.nio.IntBuffer; +import java.util.Iterator; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; @@ -51,7 +52,7 @@ import com.jogamp.nativewindow.egl.EGLGraphicsDevice; * </p> */ public class EGLDisplayUtil { - protected static final boolean DEBUG = Debug.debug("EGL"); + protected static final boolean DEBUG = Debug.debug("EGLDisplayUtil"); static LongIntHashMap eglDisplayCounter; @@ -60,6 +61,32 @@ public class EGLDisplayUtil { eglDisplayCounter.setKeyNotFoundValue(0); } + /** + * @return number of unclosed EGL Displays.<br> + */ + public static int shutdown(boolean verbose) { + if(DEBUG || verbose || eglDisplayCounter.size() > 0 ) { + System.err.println("EGLDisplayUtil.EGLDisplays: Shutdown (open: "+eglDisplayCounter.size()+")"); + if(DEBUG) { + Thread.dumpStack(); + } + if( eglDisplayCounter.size() > 0) { + EGLDisplayUtil.dumpOpenDisplayConnections(); + } + } + + return eglDisplayCounter.size(); + } + + public static void dumpOpenDisplayConnections() { + System.err.println("EGLDisplayUtil: Open EGL Display Connections: "+eglDisplayCounter.size()); + int i=0; + for(Iterator<LongIntHashMap.Entry> iter = eglDisplayCounter.iterator(); iter.hasNext(); i++) { + final LongIntHashMap.Entry e = iter.next(); + System.err.println("EGLDisplayUtil: Open["+i+"]: 0x"+Long.toHexString(e.key)+": refCnt "+e.value); + } + } + public static long eglGetDisplay(long nativeDisplay_id) { final long eglDisplay = EGL.eglGetDisplay(nativeDisplay_id); if(DEBUG) { @@ -89,6 +116,7 @@ public class EGLDisplayUtil { eglDisplayCounter.put(eglDisplay, refCnt); if(DEBUG) { System.err.println("EGLDisplayUtil.eglInitialize1("+EGLContext.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res); + // Thread.dumpStack(); } return res; } @@ -117,6 +145,7 @@ public class EGLDisplayUtil { } if(DEBUG) { System.err.println("EGLDisplayUtil.eglInitialize2("+EGLContext.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res); + // Thread.dumpStack(); } return res; } @@ -185,12 +214,13 @@ public class EGLDisplayUtil { final int refCnt = eglDisplayCounter.get(eglDisplay) - 1; // 1 - 1 = 0 -> final terminate if(0==refCnt) { // no terminate if still in use or already terminated res = EGL.eglTerminate(eglDisplay); + eglDisplayCounter.remove(eglDisplay); } else { + if(0 < refCnt) { // no negative refCount + eglDisplayCounter.put(eglDisplay, refCnt); + } res = true; } - if(0<=refCnt) { // no negative refCount - eglDisplayCounter.put(eglDisplay, refCnt); - } if(DEBUG) { System.err.println("EGLDisplayUtil.eglTerminate("+EGLContext.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res); // Thread.dumpStack(); diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index 986b110be..292eb17c8 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -64,7 +64,6 @@ import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import javax.media.opengl.GLProfile.ShutdownType; import jogamp.opengl.Debug; import jogamp.opengl.GLDrawableFactoryImpl; @@ -201,13 +200,13 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { @Override - protected final void destroy(ShutdownType shutdownType) { + protected final void destroy() { if(null != sharedMap) { Collection<SharedResource> srl = sharedMap.values(); for(Iterator<SharedResource> sri = srl.iterator(); sri.hasNext(); ) { SharedResource sr = sri.next(); if(DEBUG) { - System.err.println("EGLDrawableFactory.destroy("+shutdownType+"): "+sr.device.toString()); + System.err.println("EGLDrawableFactory.destroy(): "+sr.device.toString()); } sr.device.close(); } @@ -220,17 +219,16 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { /** * Pulling away the native library may cause havoc .. */ - if(ShutdownType.COMPLETE == shutdownType) { - if(null != eglES1DynamicLookupHelper) { - // eglES1DynamicLookupHelper.destroy(); - eglES1DynamicLookupHelper = null; - } - if(null != eglES2DynamicLookupHelper) { - // eglES2DynamicLookupHelper.destroy(); - eglES2DynamicLookupHelper = null; - } + if(null != eglES1DynamicLookupHelper) { + // eglES1DynamicLookupHelper.destroy(); + eglES1DynamicLookupHelper = null; + } + if(null != eglES2DynamicLookupHelper) { + // eglES2DynamicLookupHelper.destroy(); + eglES2DynamicLookupHelper = null; } EGLGraphicsConfigurationFactory.unregisterFactory(); + EGLDisplayUtil.shutdown(DEBUG); } private HashMap<String /*connection*/, SharedResource> sharedMap = null; diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index c1b15cac5..591fafc68 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -60,7 +60,6 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import javax.media.opengl.GLProfile.ShutdownType; import jogamp.nativewindow.macosx.OSXUtil; import jogamp.opengl.DesktopGLDynamicLookupHelper; @@ -124,7 +123,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected final void destroy(ShutdownType shutdownType) { + protected final void destroy() { if(null != sharedMap) { sharedMap.clear(); sharedMap = null; @@ -133,10 +132,9 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { /** * Pulling away the native library may cause havoc .. * - if(ShutdownType.COMPLETE == shutdownType && null != macOSXCGLDynamicLookupHelper) { - macOSXCGLDynamicLookupHelper.destroy(); - macOSXCGLDynamicLookupHelper = null; - } */ + macOSXCGLDynamicLookupHelper.destroy(); + */ + macOSXCGLDynamicLookupHelper = null; } @Override diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index c414083c4..7ea487523 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -61,7 +61,6 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import javax.media.opengl.GLProfile.ShutdownType; import jogamp.nativewindow.windows.GDI; import jogamp.nativewindow.windows.GDISurface; @@ -136,7 +135,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { @Override - protected final void destroy(ShutdownType shutdownType) { + protected final void destroy() { if(null != sharedResourceRunner) { sharedResourceRunner.stop(); sharedResourceRunner = null; @@ -149,10 +148,9 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { /** * Pulling away the native library may cause havoc .. * - if(ShutdownType.COMPLETE == shutdownType && null != windowsWGLDynamicLookupHelper) { - windowsWGLDynamicLookupHelper.destroy(); - windowsWGLDynamicLookupHelper = null; - } */ + windowsWGLDynamicLookupHelper.destroy(); + */ + windowsWGLDynamicLookupHelper = null; RegisteredClassFactory.shutdownSharedClasses(); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index 293ac96f7..bc3e5b793 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -58,7 +58,6 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import javax.media.opengl.GLProfile.ShutdownType; import jogamp.nativewindow.x11.X11Lib; import jogamp.nativewindow.x11.X11Util; @@ -129,7 +128,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected final void destroy(ShutdownType shutdownType) { + protected final void destroy() { if(null != sharedResourceRunner) { sharedResourceRunner.stop(); sharedResourceRunner = null; @@ -142,14 +141,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { /** * Pulling away the native library may cause havoc .. * - if(ShutdownType.COMPLETE == shutdownType && null != x11GLXDynamicLookupHelper) { - x11GLXDynamicLookupHelper.destroy(); - x11GLXDynamicLookupHelper = null; - } */ - - // Don't really close pending Display connections, - // since this may trigger a JVM exception - X11Util.shutdown( false, DEBUG ); + x11GLXDynamicLookupHelper.destroy(); + */ + x11GLXDynamicLookupHelper = null; } @Override |