diff options
author | Sven Gothel <[email protected]> | 2012-11-05 03:49:20 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-11-05 03:49:20 +0100 |
commit | 3a00361952120f8127a3014623de703ac696e036 (patch) | |
tree | e2c2b1d5bdddc790fcc81451f2f0ed078a97fe6d | |
parent | 0b3f9ee017f7216ec9ff37c16bbb44848aa5cfa5 (diff) |
Analyzed OSX Deadlock w/ AWT Applet & CALayer: Andres Colubri's Test Case, Commit 77db6a5c22cb4a53cf911b4caf57127770c70968
[1] - The AWT/Applet test case on OSX utilized offscreen CALayer, which is correct.
[2] - the GLEventListener.display(..) method calls Frame.setTitle(".."); which is correct,
but freezes when called right after GLEventListener.init(..)
BUG on OSX/CALayer: If frame.setTitle() is issued right after initialization
the call hangs in
at apple.awt.CWindow._setTitle(Native Method)
at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909]
Happens w/ Oracle's JRE7u9 as well!
Workaround:
- Set 'justInitialized' flag in GLEventListener.init(..)
- Clear 'justInitialized' flag in GLEventListener.display(..) at the end
- Skip Frame.setTitle(..) in GLEventListener.display(..) if 'true == justInitialized'
Somebody may send a bugreport to Oracle / OpenJDK.
3 files changed, 130 insertions, 58 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 50e070130..cc9a330a5 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -106,7 +106,7 @@ function jrun() { #D_ARGS="-Dnewt.debug.MainThread" #D_ARGS="-Dnewt.debug.Window" #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Dnativewindow.debug.NativeWindow" - D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Animator -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.GLContext.TraceSwitch" + #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Animator -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.GLContext.TraceSwitch" #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.ExtensionAvailabilityCache" #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLProfile -Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLProfile" @@ -351,8 +351,8 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.jogl.glu.TestBug463ScaleImageMemoryAWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWTCardLayoutAnimatorStartStopBug532 $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock00AWT $* -testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock01AWT $* -#testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock02AWT $* +#testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock01AWT $* +testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock02AWT $* # # swt (testswt) diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java index fa4d4a5e2..09609dd39 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java @@ -29,7 +29,9 @@ package com.jogamp.opengl.test.junit.jogl.awt; import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; @@ -61,23 +63,28 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { GLEventListener gle2 = null; @Test + public void test00NoAnimator() throws InterruptedException { + testImpl(null, 0, false); + } + + @Test public void test01Animator() throws InterruptedException { testImpl(new Animator(), 0, false); } - // @Test + @Test public void test02FPSAnimator() throws InterruptedException { testImpl(new FPSAnimator(30), 0, false); } - // @Test + @Test public void test02FPSAnimator_RestartOnAWTEDT() throws InterruptedException { - testImpl(new FPSAnimator(30), 100, false); + testImpl(new FPSAnimator(30), 200, false); } - // @Test + @Test public void test02FPSAnimator_RestartOnCurrentThread() throws InterruptedException { - testImpl(new FPSAnimator(30), 100, true); + testImpl(new FPSAnimator(30), 200, true); } void testImpl(final AnimatorBase animator, int restartPeriod, boolean restartOnCurrentThread) throws InterruptedException { @@ -109,8 +116,11 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { }); gle1 = new GLEventListener() { + boolean justInitialized = true; + @Override public void init(GLAutoDrawable drawable) { + justInitialized = true; } @Override @@ -119,8 +129,22 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { @Override public void display(GLAutoDrawable drawable) { - frame1.setTitle("f "+frameCount+", fps "+animator.getLastFPS()); + if(!justInitialized) { + // BUG on OSX/CALayer: If frame.setTitle() is issued right after initialization + // the call hangs in + // at apple.awt.CWindow._setTitle(Native Method) + // at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909] + // + final String msg = "f "+frameCount+", fps "+( null != animator ? animator.getLastFPS() : 0); + System.err.println("About to setTitle: CT "+Thread.currentThread().getName()+", "+msg+ + frame1+", displayable "+frame1.isDisplayable()+ + ", valid "+frame1.isValid()+", visible "+frame1.isVisible()); + // Thread.dumpStack(); + frame1.setTitle(msg); + + } frameCount++; + justInitialized=false; } @Override @@ -133,27 +157,37 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { glCanvas.addGLEventListener(gle1); glCanvas.addGLEventListener(gle2); - animator.setUpdateFPSFrames(60, System.err); - animator.add(glCanvas); - animator.start(); + if(null != animator) { + System.err.println("About to start Animator: CT "+Thread.currentThread().getName()); + animator.setUpdateFPSFrames(60, System.err); + animator.add(glCanvas); + animator.start(); + } attachGLCanvas(applet1, glCanvas, false); + System.err.println("About to setVisible.0 CT "+Thread.currentThread().getName()); try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + System.err.println("About to setVisible.1.0 CT "+Thread.currentThread().getName()); frame1.setVisible(true); + System.err.println("About to setVisible.1.X CT "+Thread.currentThread().getName()); }}); } catch (Throwable t) { t.printStackTrace(); Assume.assumeNoException(t); } + System.err.println("About to setVisible.X CT "+Thread.currentThread().getName()); final long sleep = 0 < restartPeriod ? restartPeriod : 100; long togo = durationPerTest; while( 0 < togo ) { + if(null == animator) { + glCanvas.display(); + } if(0 < restartPeriod) { - glCanvas = restart(applet1, glCanvas, restartOnCurrentThread); + glCanvas = restart(frame1, applet1, glCanvas, restartOnCurrentThread); } Thread.sleep(sleep); @@ -162,12 +196,30 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { } dispose(frame1, applet1); - animator.stop(); + if(null != animator) { + animator.stop(); + } gle1 = null; gle2 = null; } + int frameCount = 0; + + GLCanvas createGLCanvas() { + System.err.println("*** createGLCanvas.0"); + final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + // Iff using offscreen layer, use pbuffer, hence restore onscreen:=true. + // caps.setPBuffer(true); + // caps.setOnscreen(true); + final GLCanvas glCanvas = new GLCanvas(caps); + glCanvas.setBounds(0, 0, width, height); + Assert.assertNotNull(glCanvas); + System.err.println("*** createGLCanvas.X"); + frameCount = 0; + return glCanvas; + } + void dispose(final Frame frame, final Applet applet) { try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { @@ -181,14 +233,14 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { } } - GLCanvas restart(final Applet frame, GLCanvas glCanvas, boolean restartOnCurrentThread) throws InterruptedException { + GLCanvas restart(final Frame frame, final Applet applet, GLCanvas glCanvas, boolean restartOnCurrentThread) throws InterruptedException { glCanvas.disposeGLEventListener(gle1, true); glCanvas.disposeGLEventListener(gle2, true); - detachGLCanvas(frame, glCanvas, restartOnCurrentThread); + detachGLCanvas(applet, glCanvas, restartOnCurrentThread); glCanvas = createGLCanvas(); - attachGLCanvas(frame, glCanvas, restartOnCurrentThread); + attachGLCanvas(applet, glCanvas, restartOnCurrentThread); glCanvas.addGLEventListener(gle1); glCanvas.addGLEventListener(gle2); @@ -226,7 +278,7 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { - applet.remove(glCanvas); + applet.remove(glCanvas); applet.validate(); }}); } catch (Throwable t) { @@ -237,17 +289,6 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { System.err.println("*** detachGLCanvas.X"); } - int frameCount = 0; - - GLCanvas createGLCanvas() { - System.err.println("*** createGLCanvas.0"); - final GLCanvas glCanvas = new GLCanvas(); - glCanvas.setBounds(0, 0, width, height); - Assert.assertNotNull(glCanvas); - System.err.println("*** createGLCanvas.X"); - return glCanvas; - } - public static void main(String args[]) { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java index 7ea4a23fa..a74286232 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java @@ -43,6 +43,7 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.lang.reflect.InvocationTargetException; import java.util.Timer; import java.util.TimerTask; @@ -123,7 +124,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { private int frameCount = 0; - void run() { + void run() throws InterruptedException, InvocationTargetException { // Thread loop = new Thread("Animation Thread") { // public void run() { frameCount = 0; @@ -133,7 +134,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { } if (restartCanvas && restartTimeout == frameCount) { - // restart(); + restart(); } if (useAnimator) { @@ -155,7 +156,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { // loop.start(); } - void setup() { + void setup() throws InterruptedException, InvocationTargetException { if (printThreadInfo) System.out.println("Current thread at setup(): " + Thread.currentThread()); millisOffset = System.currentTimeMillis(); @@ -214,11 +215,18 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { frame.add(this); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { - dispose(); + try { + dispose(); + } catch (Exception ex) { + Assume.assumeNoException(ex); + } } }); - frame.setVisible(true); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(true); // from here on all AWT mods must be done on AWT-EDT ! + } } ); // Canvas setup ---------------------------------------------------------- @@ -227,17 +235,21 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { capabilities.setSampleBuffers(true); capabilities.setNumSamples(numSamples); capabilities.setDepthBits(24); - capabilities.setStencilBits(8); + // capabilities.setStencilBits(8); // No Stencil on OSX w/ hw-accel ! capabilities.setAlphaBits(8); canvas = new GLCanvas(capabilities); canvas.setBounds(0, 0, width, height); - this.setLayout(new BorderLayout()); - this.add(canvas, BorderLayout.CENTER); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + MiniPApplet.this.setLayout(new BorderLayout()); + MiniPApplet.this.add(canvas, BorderLayout.CENTER); + MiniPApplet.this.validate(); + } } ); canvas.addMouseMotionListener(this); canvas.addKeyListener(this); - + // Setting up animation listener = new SimpleListener(); canvas.addGLEventListener(listener); @@ -248,7 +260,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { initialized = true; } - void restart() { + void restart() throws InterruptedException, InvocationTargetException { System.out.println("Restarting surface..."); // Stopping animation, removing current canvas. @@ -267,8 +279,12 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { canvas.setBounds(0, 0, width, height); // Setting up animation again - this.setLayout(new BorderLayout()); - this.add(canvas, BorderLayout.CENTER); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + MiniPApplet.this.setLayout(new BorderLayout()); + MiniPApplet.this.add(canvas, BorderLayout.CENTER); + MiniPApplet.this.validate(); + } } ); canvas.addMouseMotionListener(this); canvas.addKeyListener(this); @@ -284,7 +300,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { System.out.println("Done"); } - void dispose() { + void dispose() throws InterruptedException, InvocationTargetException { if( null == frame ) { return; } @@ -302,24 +318,28 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { frame.dispose(); frame = null; } else { - try { - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - MiniPApplet.this.remove(canvas); - frame.remove(MiniPApplet.this); - frame.validate(); - frame.dispose(); - frame = null; - }}); - } catch (Throwable t) { - t.printStackTrace(); - Assume.assumeNoException(t); - } + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + MiniPApplet.this.remove(canvas); + frame.remove(MiniPApplet.this); + frame.validate(); + frame.dispose(); + frame = null; + }}); } } + boolean justInitialized = true; + void draw(GL2 gl) { - frame.setTitle("frame " + frameCount); + if(!justInitialized) { + // BUG on OSX/CALayer: If frame.setTitle() is issued right after initialization + // the call hangs in + // at apple.awt.CWindow._setTitle(Native Method) + // at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909] + // + frame.setTitle("frame " + frameCount); + } if (printThreadInfo) System.out.println("Current thread at draw(): " + Thread.currentThread()); @@ -336,6 +356,10 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { int[] temp = { 0 }; gl.glGetIntegerv(GL2.GL_MAX_SAMPLES, temp, 0); System.out.println("Maximum number of samples supported by the hardware: " + temp[0]); + System.out.println("Frame: "+frame); + System.out.println("Applet: "+MiniPApplet.this); + System.out.println("GLCanvas: "+canvas); + System.out.println("GLDrawable: "+canvas.getDelegatedDrawable()); } if (currentSamples == -1) { @@ -418,13 +442,16 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { @Override public void display(GLAutoDrawable drawable) { draw(drawable.getGL().getGL2()); + justInitialized = false; } @Override public void dispose(GLAutoDrawable drawable) { } @Override - public void init(GLAutoDrawable drawable) { } + public void init(GLAutoDrawable drawable) { + justInitialized = true; + } @Override public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) { } @@ -588,7 +615,11 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { throw new RuntimeException(e); } if (mini != null) { - mini.run(); + try { + mini.run(); + } catch (Exception ex) { + Assume.assumeNoException(ex); + } } } |