diff options
author | Sven Gothel <sgothel@jausoft.com> | 2015-09-15 07:50:50 +0200 |
---|---|---|
committer | Sven Gothel <sgothel@jausoft.com> | 2015-09-15 07:50:50 +0200 |
commit | 68c8e39fa8d6e700f0a99241c1a01a435b7f6284 (patch) | |
tree | d02cf789a06514da205f6da8a45f55538b019a0b /src/newt/classes/jogamp | |
parent | cf9b31c30de3768447b20d6aa31ec1df00595871 (diff) |
Bug 1211: Hardening Condition-Wait from Spurious-Wakeups and unintended InterruptedException(s)
Below is an updated list of Condition-Wait classifications
as described in Bug 1211.
This list includes recent changes on GlueGen
regarding this Bug 1211.
A followup commit will address the unit tests.
- Noncancelable + Persistent-Wait
- GLMediaPlayerImpl.StreamWorker thread (changed)
- pauses thread in case of intr
- Cancelable + Persistent-Wait:
- LFRingbuffer.getImpl(..)
- LFRingbuffer.waitForFreeSlots(int)
- SyncedRingbuffer.getImpl(..)
- SyncedRingbuffer.waitForFreeSlots(int)
- FunctionTask.invokeOnNewThread(..) (changed)
- RunnableTask.invokeOnNewThread(..) (changed)
- SharedResourceRunner.run()
- SharedResourceRunner.doAndWait() (changed)
- SharedResourceRunner.start() (changed)
- SharedResourceRunner.stop() (changed)
- GLMediaPlayerImpl.StreamWorker ctor (changed)
- GLMediaPlayerImpl caller thread actions do*() (changed)
- AndroidGLMediaPlayerAPI14.getNextTextureImpl(..) (changed)
- DisplayImpl.enqueueEvent(..) (changed)
-> Persistent-Wait
-> Cancels wait and NEWTEvent
-> dispatchMessage(NEWTEventTask): always notifyCaller!
- GLDrawableHelper.invoke(..) (changed)
- DefaultEDTUtil.waitUntilIdle() (changed)
- DefaultEDTUtil.waitUntilStopped() (changed)
- DefaultEDTUtil.invokeImpl(..) (changed)
- DefaultEDTUtil.NEDT.run(..) (changed)
- AWTEDTUtil.waitUntilStopped(..) (changed)
- AWTEDTUtil.invokeImpl(..) (changed)
- AWTEDTUtil.NEDT.run(..) (changed)
- SWTEDTUtil.invokeImpl(..) (changed)
- SWTEDTUtil.waitUntilStopped(..) (changed)
- SWTEDTUtil.NEDT.run(..) (changed)
- GLWorkerThread.invokeAndWait(..)
- GLWorkerThread.start() (changed)
- GLWorkerThread.WorkerRunnable.run() (changed)
- Animator.run() (changed)
- AnimatorBase.finishLifecycleAction() (changed)
- OSXUtil.RunOnMainThread(..) (changed)
- SingletonInstanceServerSocket.Server.shutdown() (changed)
- SingletonInstanceServerSocket.Server.start() (changed)
- com.jogamp.audio.windows.waveout.Mixer.shutdown() (changed)
- Extending/Using InterruptSource.Thread (changed)
- DefaultEDTUtil.NEDT
- AWTEDTUtil.NEDT
- SWTEDTUtil.NEDT
- GLWorkerThread.thread
- Mixer.FillerThread
- Mixer.MixerThread
- Using InterruptSource.Thread (changed)
- TempFileCache
- LauncherTempFileCache
- Animator.thread
- SingletonInstanceServerSocket.Server.serverThread
Deprecated:
- FunctionTask.invoke(..) (changed)
-> on current thread, no wait -> deprecated
- RunnableTask.invoke(..) (changed)
-> on current thread, no wait -> deprecated
Diffstat (limited to 'src/newt/classes/jogamp')
8 files changed, 88 insertions, 58 deletions
diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java index bf46ce609..ff713410b 100644 --- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java +++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java @@ -44,6 +44,8 @@ import com.jogamp.nativewindow.NativeWindowException; import jogamp.common.util.locks.LockDebugUtil; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.RunnableTask; import com.jogamp.common.util.locks.Lock; import com.jogamp.newt.util.EDTUtil; @@ -68,7 +70,7 @@ public class DefaultEDTUtil implements EDTUtil { this.threadGroup = tg; this.name=Thread.currentThread().getName()+"-"+name+"-EDT-"; this.dispatchMessages=dispatchMessages; - this.edt = new NEDT(threadGroup, name); + this.edt = new NEDT(threadGroup, this.name); this.edt.setDaemon(true); // don't stop JVM from shutdown .. } @@ -169,8 +171,7 @@ public class DefaultEDTUtil implements EDTUtil { }; private final boolean invokeImpl(boolean wait, Runnable task, final boolean stop, final boolean provokeError) { - Throwable throwable = null; - RunnableTask rTask = null; + final RunnableTask rTask; final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status @@ -187,6 +188,7 @@ public class DefaultEDTUtil implements EDTUtil { task.run(); } wait = false; // running in same thread (EDT) -> no wait + rTask = null; if( stop ) { edt.shouldStop = true; if( edt.tasks.size()>0 ) { @@ -230,18 +232,19 @@ public class DefaultEDTUtil implements EDTUtil { } } else { wait = false; + rTask = null; } } } if( wait ) { try { - rTaskLock.wait(); // free lock, allow execution of rTask + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); + throw new InterruptedRuntimeException(ie); } + final Throwable throwable = rTask.getThrowable(); if(null!=throwable) { if(throwable instanceof NativeWindowException) { throw (NativeWindowException)throwable; @@ -268,13 +271,13 @@ public class DefaultEDTUtil implements EDTUtil { return false; } synchronized(_edt.tasks) { - while(_edt.isRunning && _edt.tasks.size()>0) { - try { + try { + while(_edt.isRunning && _edt.tasks.size()>0) { _edt.tasks.notifyAll(); _edt.tasks.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } @@ -284,12 +287,12 @@ public class DefaultEDTUtil implements EDTUtil { final public boolean waitUntilStopped() { synchronized(edtLock) { if(edt.isRunning && edt != Thread.currentThread() ) { - while( edt.isRunning ) { - try { + try { + while( edt.isRunning ) { edtLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } else { @@ -298,13 +301,13 @@ public class DefaultEDTUtil implements EDTUtil { } } - class NEDT extends Thread { + class NEDT extends InterruptSource.Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; final ArrayList<RunnableTask> tasks = new ArrayList<RunnableTask>(); // one shot tasks public NEDT(final ThreadGroup tg, final String name) { - super(tg, name); + super(tg, null, name); } final public boolean isRunning() { @@ -347,11 +350,11 @@ public class DefaultEDTUtil implements EDTUtil { RunnableTask task = null; synchronized(tasks) { // wait for tasks - if(!shouldStop && tasks.size()==0) { + if( !shouldStop && tasks.size()==0 ) { try { tasks.wait(pollPeriod); } catch (final InterruptedException e) { - e.printStackTrace(); + throw new InterruptedRuntimeException(e); } } // execute one task, if available @@ -375,7 +378,7 @@ public class DefaultEDTUtil implements EDTUtil { } if(!task.hasWaiter() && null != task.getThrowable()) { // at least dump stack-trace in case nobody waits for result - System.err.println("DefaultEDT.run(): Caught exception occured on thread "+Thread.currentThread().getName()+": "+task.toString()); + System.err.println("DefaultEDT.run(): Caught exception occured on thread "+java.lang.Thread.currentThread().getName()+": "+task.toString()); task.getThrowable().printStackTrace(); } } diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index cc1f3d8e0..c1cd6db32 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -37,6 +37,7 @@ package jogamp.newt; import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.IOUtil; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.newt.Display; import com.jogamp.newt.NewtFactory; @@ -697,8 +698,9 @@ public abstract class DisplayImpl extends Display { } else { throw re; } + } finally { + eventTask.notifyCaller(); } - eventTask.notifyCaller(); } @Override @@ -725,7 +727,10 @@ public abstract class DisplayImpl extends Display { } if( null != _events ) { for (int i=0; i < _events.size(); i++) { - dispatchMessage(_events.get(i)); + final NEWTEventTask e = _events.get(i); + if( !e.isDispatched() ) { + dispatchMessage(e); + } } } } @@ -759,11 +764,12 @@ public abstract class DisplayImpl extends Display { haveEvents = true; eventsLock.notifyAll(); } - if( wait ) { + while( wait && !eTask.isDispatched() ) { try { lock.wait(); } catch (final InterruptedException ie) { - throw new RuntimeException(ie); + eTask.setDispatched(); // Cancels NEWTEvent .. + throw new InterruptedRuntimeException(ie); } if( null != eTask.getException() ) { throw eTask.getException(); diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java index 9d3121635..3d9073769 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java @@ -33,6 +33,8 @@ import java.awt.EventQueue; import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.RunnableTask; import com.jogamp.common.util.awt.AWTEDTExecutor; import com.jogamp.newt.util.EDTUtil; @@ -54,7 +56,7 @@ public class AWTEDTUtil implements EDTUtil { this.threadGroup = tg; this.name=Thread.currentThread().getName()+"-"+name+"-EDT-"; this.dispatchMessages=dispatchMessages; - this.nedt = new NEDT(threadGroup, name); + this.nedt = new NEDT(threadGroup, this.name); this.nedt.setDaemon(true); // don't stop JVM from shutdown .. } @@ -132,8 +134,7 @@ public class AWTEDTUtil implements EDTUtil { } private final boolean invokeImpl(boolean wait, final Runnable task, final boolean stop) { - Throwable throwable = null; - RunnableTask rTask = null; + final RunnableTask rTask; final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status @@ -150,6 +151,7 @@ public class AWTEDTUtil implements EDTUtil { task.run(); } wait = false; // running in same thread (EDT) -> no wait + rTask = null; if(stop) { nedt.shouldStop = true; } @@ -182,18 +184,21 @@ public class AWTEDTUtil implements EDTUtil { true /* always catch and report Exceptions, don't disturb EDT */, wait ? null : System.err); AWTEDTExecutor.singleton.invoke(false, rTask); + } else { + wait = false; + rTask = null; } } } if( wait ) { try { - rTaskLock.wait(); // free lock, allow execution of rTask + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); + throw new InterruptedRuntimeException(ie); } + final Throwable throwable = rTask.getThrowable(); if(null!=throwable) { if(throwable instanceof NativeWindowException) { throw (NativeWindowException)throwable; @@ -227,12 +232,12 @@ public class AWTEDTUtil implements EDTUtil { final public boolean waitUntilStopped() { synchronized(edtLock) { if( nedt.isRunning && nedt != Thread.currentThread() && !EventQueue.isDispatchThread() ) { - while( nedt.isRunning ) { - try { + try { + while( nedt.isRunning ) { edtLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } else { @@ -241,13 +246,13 @@ public class AWTEDTUtil implements EDTUtil { } } - class NEDT extends Thread { + class NEDT extends InterruptSource.Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; Object sync = new Object(); public NEDT(final ThreadGroup tg, final String name) { - super(tg, name); + super(tg, null, name); } final public boolean isRunning() { @@ -286,7 +291,7 @@ public class AWTEDTUtil implements EDTUtil { try { sync.wait(pollPeriod); } catch (final InterruptedException e) { - e.printStackTrace(); + throw new InterruptedRuntimeException(e); } } } diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java index bc0bfaa16..c3b7bff36 100644 --- a/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java +++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java @@ -43,6 +43,7 @@ import jogamp.newt.WindowImpl; import jogamp.newt.driver.KeyTracker; import com.jogamp.common.nio.StructAccessor; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.Window; import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.WindowEvent; @@ -63,7 +64,7 @@ public class LinuxEventDeviceTracker implements WindowListener, KeyTracker { static { ledt = new LinuxEventDeviceTracker(); - final Thread t = new Thread(ledt.eventDeviceManager, "NEWT-LinuxEventDeviceManager"); + final Thread t = new InterruptSource.Thread(null, ledt.eventDeviceManager, "NEWT-LinuxEventDeviceManager"); t.setDaemon(true); t.start(); } @@ -153,7 +154,7 @@ public class LinuxEventDeviceTracker implements WindowListener, KeyTracker { if(number<32&&number>=0) { if(eventDevicePollers[number]==null){ eventDevicePollers[number] = new EventDevicePoller(number); - final Thread t = new Thread(eventDevicePollers[number], "NEWT-LinuxEventDeviceTracker-event"+number); + final Thread t = new InterruptSource.Thread(null, eventDevicePollers[number], "NEWT-LinuxEventDeviceTracker-event"+number); t.setDaemon(true); t.start(); } else if(eventDevicePollers[number].stop) { diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java index f40728da0..53bb9c3a5 100644 --- a/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java +++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java @@ -37,6 +37,7 @@ import java.io.InputStream; import jogamp.newt.WindowImpl; import jogamp.newt.driver.MouseTracker; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseEvent; @@ -55,7 +56,7 @@ public class LinuxMouseTracker implements WindowListener, MouseTracker { static { lmt = new LinuxMouseTracker(); - final Thread t = new Thread(lmt.mouseDevicePoller, "NEWT-LinuxMouseTracker"); + final Thread t = new InterruptSource.Thread(null, lmt.mouseDevicePoller, "NEWT-LinuxMouseTracker"); t.setDaemon(true); t.start(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index a38ba4c13..2bbcdce38 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -34,6 +34,7 @@ package jogamp.newt.driver.macosx; +import com.jogamp.common.util.InterruptSource; import com.jogamp.nativewindow.AbstractGraphicsConfiguration; import com.jogamp.nativewindow.GraphicsConfigurationFactory; import com.jogamp.nativewindow.NativeWindow; @@ -378,7 +379,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } private void superSizeChangedOffThread(final boolean defer, final int newWidth, final int newHeight, final boolean force) { if( defer ) { - new Thread() { + new InterruptSource.Thread() { public void run() { WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force); } }.start(); diff --git a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java index 2bdab2796..260a1beb4 100644 --- a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java +++ b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java @@ -38,19 +38,27 @@ public class NEWTEventTask { private final NEWTEvent event; private final Object notifyObject; private RuntimeException exception; + private volatile boolean dispatched; public NEWTEventTask(final NEWTEvent event, final Object notifyObject) { this.event = event ; this.notifyObject = notifyObject ; this.exception = null; + this.dispatched = false; } public final NEWTEvent get() { return event; } public final void setException(final RuntimeException e) { exception = e; } public final RuntimeException getException() { return exception; } public final boolean isCallerWaiting() { return null != notifyObject; } + public final boolean isDispatched() { return dispatched; } + public final void setDispatched() { dispatched = true; } + /** + * Notifies caller after {@link #setDispatched()}. + */ public void notifyCaller() { + setDispatched(); if(null != notifyObject) { synchronized (notifyObject) { notifyObject.notifyAll(); diff --git a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java index 9039b6083..9d2b41bbc 100644 --- a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java @@ -32,6 +32,8 @@ import com.jogamp.nativewindow.NativeWindowException; import jogamp.newt.Debug; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.RunnableTask; import com.jogamp.newt.util.EDTUtil; @@ -162,8 +164,7 @@ public class SWTEDTUtil implements EDTUtil { } private final boolean invokeImpl(boolean wait, final Runnable task, boolean stop) { - Throwable throwable = null; - RunnableTask rTask = null; + final RunnableTask rTask; final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status @@ -184,6 +185,7 @@ public class SWTEDTUtil implements EDTUtil { task.run(); } wait = false; // running in same thread (EDT) -> no wait + rTask = null; if( stop ) { nedt.shouldStop = true; } @@ -225,18 +227,21 @@ public class SWTEDTUtil implements EDTUtil { true /* always catch and report Exceptions, don't disturb EDT */, wait ? null : System.err); swtDisplay.asyncExec(rTask); + } else { + wait = false; + rTask = null; } } } if( wait ) { try { - rTaskLock.wait(); // free lock, allow execution of rTask + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); + throw new InterruptedRuntimeException(ie); } + final Throwable throwable = rTask.getThrowable(); if(null!=throwable) { if(throwable instanceof NativeWindowException) { throw (NativeWindowException)throwable; @@ -274,12 +279,12 @@ public class SWTEDTUtil implements EDTUtil { final Thread swtT = !swtDisplay.isDisposed() ? swtDisplay.getThread() : null; final boolean onSWTEDT = swtT == curT; if( nedt.isRunning && nedt != curT && !onSWTEDT ) { - while( nedt.isRunning ) { - try { + try { + while( nedt.isRunning ) { edtLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } else { @@ -288,13 +293,13 @@ public class SWTEDTUtil implements EDTUtil { } } - class NEDT extends Thread { + class NEDT extends InterruptSource.Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; Object sync = new Object(); public NEDT(final ThreadGroup tg, final String name) { - super(tg, name); + super(tg, null, name); } final public boolean isRunning() { @@ -337,7 +342,7 @@ public class SWTEDTUtil implements EDTUtil { try { sync.wait(pollPeriod); } catch (final InterruptedException e) { - e.printStackTrace(); + throw new InterruptedRuntimeException(e); } } } |