From f2cfb6119a3663715ed2d572643949b3bef58662 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Fri, 7 Sep 2012 08:13:06 +0200
Subject: 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.
---
.../javax/media/opengl/GLDrawableFactory.java | 36 +++---
src/jogl/classes/javax/media/opengl/GLProfile.java | 29 +----
.../classes/jogamp/opengl/egl/EGLDisplayUtil.java | 38 +++++-
.../jogamp/opengl/egl/EGLDrawableFactory.java | 22 ++--
.../macosx/cgl/MacOSXCGLDrawableFactory.java | 10 +-
.../windows/wgl/WindowsWGLDrawableFactory.java | 10 +-
.../opengl/x11/glx/X11GLXDrawableFactory.java | 14 +--
.../media/nativewindow/NativeWindowFactory.java | 42 +++++--
.../classes/jogamp/nativewindow/jawt/JAWTUtil.java | 11 +-
.../jogamp/nativewindow/macosx/OSXUtil.java | 10 ++
.../jogamp/nativewindow/windows/GDIUtil.java | 10 ++
.../classes/jogamp/nativewindow/x11/X11Util.java | 127 +++++++++++++--------
.../junit/jogl/acore/TestShutdownCompleteAWT.java | 4 +-
.../junit/jogl/acore/TestShutdownCompleteNEWT.java | 14 ++-
.../junit/jogl/acore/TestShutdownSharedAWT.java | 124 --------------------
.../junit/jogl/acore/TestShutdownSharedNEWT.java | 127 ---------------------
.../jogl/demos/es2/newt/TestGearsES2NEWT.java | 13 +--
.../jogl/demos/es2/newt/TestRedSquareES2NEWT.java | 13 +--
.../test/junit/newt/TestScreenMode01NEWT.java | 2 +-
19 files changed, 237 insertions(+), 419 deletions(-)
delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownSharedAWT.java
delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownSharedNEWT.java
(limited to 'src')
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() {
@@ -218,20 +224,6 @@ public abstract class GLDrawableFactory {
factoryShutdownHookRegistered = true;
}
- private static synchronized void unregisterFactoryShutdownHook() {
- if (!factoryShutdownHookRegistered) {
- return;
- }
- AccessController.doPrivileged(new PrivilegedAction
*/
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.
+ */
+ 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 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 srl = sharedMap.values();
for(Iterator 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 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
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index afcd0a008..89d476a3b 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -102,6 +102,8 @@ public abstract class NativeWindowFactory {
private static Constructor> x11ToolkitLockConstructor;
private static boolean requiresToolkitLock;
+ private static volatile boolean isJVMShuttingDown = false;
+
/** Creates a new NativeWindowFactory instance. End users do not
need to call this method. */
protected NativeWindowFactory() {
@@ -168,6 +170,22 @@ public abstract class NativeWindowFactory {
}
}
+ private static void shutdownNativeImpl(final ClassLoader cl) {
+ final String clazzName;
+ if( TYPE_X11 == nativeWindowingTypePure ) {
+ clazzName = X11UtilClassName;
+ } else if( TYPE_WINDOWS == nativeWindowingTypePure ) {
+ clazzName = GDIClassName;
+ } else if( TYPE_MACOSX == nativeWindowingTypePure ) {
+ clazzName = OSXUtilClassName;
+ } else {
+ clazzName = null;
+ }
+ if( null != clazzName ) {
+ ReflectionUtil.callStaticMethod(clazzName, "shutdown", null, null, cl );
+ }
+ }
+
/**
* Static one time initialization of this factory.
* This initialization method must be called once by the program or utilizing modules!
@@ -268,22 +286,28 @@ public abstract class NativeWindowFactory {
}
}
- public static synchronized void shutdown() {
+ public static synchronized void shutdown(boolean _isJVMShuttingDown) {
+ isJVMShuttingDown = _isJVMShuttingDown;
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() START: JVM Shutdown "+isJVMShuttingDown);
+ }
if(initialized) {
initialized = false;
- if(DEBUG) {
- System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() START");
+ if(null != registeredFactories) {
+ registeredFactories.clear();
+ registeredFactories = null;
}
- registeredFactories.clear();
- registeredFactories = null;
GraphicsConfigurationFactory.shutdown();
- // X11Util.shutdown(..) already called via GLDrawableFactory.shutdown() ..
- if(DEBUG) {
- System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() END");
- }
+ }
+ shutdownNativeImpl(NativeWindowFactory.class.getClassLoader()); // always re-shutdown
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() END JVM Shutdown "+isJVMShuttingDown);
}
}
+ /** Returns true if the JVM is shutting down, otherwise false. */
+ public static final boolean isJVMShuttingDown() { return isJVMShuttingDown; }
+
/** @return true if the underlying toolkit requires locking, otherwise false. */
public static boolean requiresToolkitLock() {
return requiresToolkitLock;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
index 36d7c3727..f1e8a786a 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
@@ -48,6 +48,7 @@ import java.util.ArrayList;
import java.util.Map;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ToolkitLock;
import jogamp.nativewindow.Debug;
@@ -271,10 +272,18 @@ public class JAWTUtil {
}
}
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ */
public static void initSingleton() {
// just exist to ensure static init has been run
}
-
+
+ /**
+ * Called by {@link NativeWindowFactory#shutdown()}
+ */
+ public static void shutdown() {
+ }
public static boolean hasJava2D() {
return j2dExist;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index f5f735051..149ebdf4a 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -28,6 +28,7 @@
package jogamp.nativewindow.macosx;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
@@ -38,6 +39,9 @@ public class OSXUtil {
private static boolean isInit = false;
private static final boolean DEBUG = Debug.debug("OSXUtil");
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ */
public static synchronized void initSingleton() {
if(!isInit) {
if(DEBUG) {
@@ -54,6 +58,12 @@ public class OSXUtil {
}
}
+ /**
+ * Called by {@link NativeWindowFactory#shutdown()}
+ */
+ public static void shutdown() {
+ }
+
public static boolean requiresToolkitLock() {
return false;
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
index fda1649b6..613c76032 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
@@ -29,6 +29,7 @@ package jogamp.nativewindow.windows;
import javax.media.nativewindow.util.Point;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.NativeWindowFactory;
import jogamp.nativewindow.NWJNILibLoader;
import jogamp.nativewindow.Debug;
@@ -41,6 +42,9 @@ public class GDIUtil {
private static RegisteredClassFactory dummyWindowClassFactory;
private static boolean isInit = false;
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ */
public static synchronized void initSingleton() {
if(!isInit) {
synchronized(X11Util.class) {
@@ -61,6 +65,12 @@ public class GDIUtil {
}
}
+ /**
+ * Called by {@link NativeWindowFactory#shutdown()}
+ */
+ public static void shutdown() {
+ }
+
public static boolean requiresToolkitLock() { return false; }
private static RegisteredClass dummyWindowClass = null;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index 860238649..93b7f3487 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -67,13 +67,13 @@ public class X11Util {
*
*
* You may test this, ie just reverse the destroy order below.
- * See also native test: jogl/test/native/displayMultiple02.c
+ * See also native test: jogl/test-native/displayMultiple02.c
*
*
* Workaround is to not close them at all if driver vendor is ATI.
*
*/
- public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = true;
+ public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG", true);
/** Value is true, best 'stable' results if always using XInitThreads(). */
public static final boolean XINITTHREADS_ALWAYS_ENABLED = true;
@@ -95,6 +95,9 @@ public class X11Util {
private static Object setX11ErrorHandlerLock = new Object();
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ */
public static void initSingleton() {
if(!isInit) {
synchronized(X11Util.class) {
@@ -138,6 +141,52 @@ public class X11Util {
}
}
+ /**
+ * Cleanup resources.
+ *
+ * Called by {@link NativeWindowFactory#shutdown()}
+ *
+ */
+ public static void shutdown() {
+ if(isInit) {
+ synchronized(X11Util.class) {
+ if(isInit) {
+ final boolean isJVMShuttingDown = NativeWindowFactory.isJVMShuttingDown() ;
+ if(DEBUG || openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0) {
+ System.err.println("X11Util.Display: Shutdown (JVM shutdown: "+isJVMShuttingDown+
+ ", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+
+ ", reusable (open, marked uncloseable): "+reusableDisplayList.size()+
+ ", pending (post closing): "+pendingDisplayList.size()+
+ ")");
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ if( openDisplayList.size() > 0) {
+ X11Util.dumpOpenDisplayConnections();
+ }
+ if( reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0 ) {
+ X11Util.dumpPendingDisplayConnections();
+ }
+ }
+
+ synchronized(globalLock) {
+ // Only at JVM shutdown time, since AWT impl. seems to
+ // dislike closing of X11 Display's (w/ ATI driver).
+ if( isJVMShuttingDown ) {
+ isInit = false;
+ closePendingDisplayConnections();
+ openDisplayList.clear();
+ reusableDisplayList.clear();
+ pendingDisplayList.clear();
+ openDisplayMap.clear();
+ shutdown0();
+ }
+ }
+ }
+ }
+ }
+ }
+
public static synchronized boolean isNativeLockAvailable() {
return isX11LockAvailable;
}
@@ -183,6 +232,7 @@ public class X11Util {
private static Object globalLock = new Object();
private static LongObjectHashMap openDisplayMap = new LongObjectHashMap(); // handle -> name
private static List openDisplayList = new ArrayList();
+ private static List reusableDisplayList = new ArrayList();
private static List pendingDisplayList = new ArrayList();
public static class NamedDisplay {
@@ -218,8 +268,7 @@ public class X11Util {
public final boolean equals(Object obj) {
if(this == obj) { return true; }
if(obj instanceof NamedDisplay) {
- NamedDisplay n = (NamedDisplay) obj;
- return handle == n.handle;
+ return handle == ((NamedDisplay) obj).handle;
}
return false;
}
@@ -246,43 +295,6 @@ public class X11Util {
}
}
- /**
- * Cleanup resources.
- * If realXCloseOpenAndPendingDisplays is false,
- * keep alive all references (open display connection) for restart on same ClassLoader.
- *
- * @return number of unclosed X11 Displays.
- * @param realXCloseOpenAndPendingDisplays if true, {@link #closePendingDisplayConnections()} is called.
- */
- public static int shutdown(boolean realXCloseOpenAndPendingDisplays, boolean verbose) {
- int num=0;
- if(DEBUG || verbose || openDisplayMap.size() > 0 || pendingDisplayList.size() > 0) {
- System.err.println("X11Util.Display: Shutdown (close open / pending Displays: "+realXCloseOpenAndPendingDisplays+
- ", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+
- ", pending (not closed, marked uncloseable): "+pendingDisplayList.size()+")");
- if(DEBUG) {
- Thread.dumpStack();
- }
- if( openDisplayList.size() > 0) {
- X11Util.dumpOpenDisplayConnections();
- }
- if( pendingDisplayList.size() > 0 ) {
- X11Util.dumpPendingDisplayConnections();
- }
- }
-
- synchronized(globalLock) {
- if(realXCloseOpenAndPendingDisplays) {
- closePendingDisplayConnections();
- openDisplayList.clear();
- pendingDisplayList.clear();
- openDisplayMap.clear();
- shutdown0();
- }
- }
- return num;
- }
-
/**
* Closing pending Display connections in reverse order.
*
@@ -292,9 +304,9 @@ public class X11Util {
int num=0;
synchronized(globalLock) {
if(DEBUG) {
- System.err.println("X11Util: Closing Pending X11 Display Connections: "+pendingDisplayList.size());
+ System.err.println("X11Util: Closing Pending X11 Display Connections in order of their creation: "+pendingDisplayList.size());
}
- for(int i=pendingDisplayList.size()-1; i>=0; i--) {
+ for(int i=0; i