From cef7ba607ad7e8eb1ff2a438d77710a29aa0bda6 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 22 Sep 2014 23:17:28 +0200 Subject: Fix synchronization issues in GLDrawableHelper.flushGLRunnables(), fixes rare deadlock with animator-exception and invoke(wait=true, ..) Fix synchronization issues in GLDrawableHelper.flushGLRunnables(): - Querying 'glRunnables.size()' is not synchronized, only its reference is volatile, not the instance's own states. - 'flushGLRunnable()' must operates while acquired the 'glRunnable' lock. - 'glRunnables' are no more volatile - introduced volatile 'glRunnableCount', allowing 'display(..)' method to pre-query whether blocking 'execGLRunnables(..)' must be called. This is risk (deadlock) free. Also fixes rare deadlock in animator display-exception / GLAD.invoke(wait=true, ..) case: - 'GLDrawableHelper.invoke(.., GLRunnable)' acquires the 'glRunnable' lock. - Then it queries animator state, which is blocking. - Hence animator's 'flushGLRunnable()' call must happen outside the animator lock --- .../classes/com/jogamp/opengl/util/Animator.java | 42 ++++++++++++---------- 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'src/jogl/classes/com/jogamp/opengl/util/Animator.java') diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java index c7a03eddb..4686e1745 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java +++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java @@ -165,7 +165,6 @@ public class Animator extends AnimatorBase { } catch (final UncaughtAnimatorException dre) { displayCaught = dre; stopIssued = true; - isAnimating = false; break; // end pause loop } } @@ -199,7 +198,6 @@ public class Animator extends AnimatorBase { } catch (final UncaughtAnimatorException dre) { displayCaught = dre; stopIssued = true; - isAnimating = false; break; // end animation loop } if ( !runAsFastAsPossible ) { @@ -226,24 +224,32 @@ public class Animator extends AnimatorBase { } } } - synchronized (Animator.this) { - if(DEBUG) { - System.err.println("Animator stop on " + animThread.getName() + ": " + toString()); - if( null != displayCaught ) { - System.err.println("Animator caught: "+displayCaught.getMessage()); - displayCaught.printStackTrace(); + boolean flushGLRunnables = false; + try { + synchronized (Animator.this) { + if(DEBUG) { + System.err.println("Animator stop on " + animThread.getName() + ": " + toString()); + if( null != displayCaught ) { + System.err.println("Animator caught: "+displayCaught.getMessage()); + displayCaught.printStackTrace(); + } } - } - stopIssued = false; - pauseIssued = false; - isAnimating = false; - try { - if( null != displayCaught ) { - handleUncaughtException(displayCaught); // may throw exception if null handler + stopIssued = false; + pauseIssued = false; + isAnimating = false; + try { + if( null != displayCaught ) { + flushGLRunnables = true; + handleUncaughtException(displayCaught); // may throw exception if null handler + } + } finally { + animThread = null; + Animator.this.notifyAll(); } - } finally { - animThread = null; - Animator.this.notifyAll(); + } + } finally { + if( flushGLRunnables ) { + flushGLRunnables(); } } } -- cgit v1.2.3