aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/classes/jogamp
diff options
context:
space:
mode:
authorSven Gothel <sgothel@jausoft.com>2015-09-15 07:50:50 +0200
committerSven Gothel <sgothel@jausoft.com>2015-09-15 07:50:50 +0200
commit68c8e39fa8d6e700f0a99241c1a01a435b7f6284 (patch)
treed02cf789a06514da205f6da8a45f55538b019a0b /src/newt/classes/jogamp
parentcf9b31c30de3768447b20d6aa31ec1df00595871 (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')
-rw-r--r--src/newt/classes/jogamp/newt/DefaultEDTUtil.java45
-rw-r--r--src/newt/classes/jogamp/newt/DisplayImpl.java14
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java35
-rw-r--r--src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java5
-rw-r--r--src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java3
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java3
-rw-r--r--src/newt/classes/jogamp/newt/event/NEWTEventTask.java8
-rw-r--r--src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java33
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);
}
}
}