From 2da0d69fec6209c55832f5aae9d365e25d3aba6d Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 20 Jul 2012 12:46:35 +0200 Subject: Fix NEWT exception handling in event dispatching: Catch and fwd to caller Exceptions caused by NEWTEvent processing (on it's EDT) were not propagated to the caller (diff thread). Hence the EDT were brought down and the caller may have waited forever (deadlock). Catch exception if caller waits and throw exception at waiting point. --- src/newt/classes/jogamp/newt/DefaultEDTUtil.java | 2 +- src/newt/classes/jogamp/newt/DisplayImpl.java | 56 ++++++++++++++-------- .../classes/jogamp/newt/event/NEWTEventTask.java | 13 +++-- 3 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java index fd757fba6..bdbe96070 100644 --- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java +++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java @@ -340,7 +340,7 @@ public class DefaultEDTUtil implements EDTUtil { } } if(DEBUG) { - System.err.println(getName()+": EDT run() EXIT "+ getName()+", "+error); + System.err.println(getName()+": EDT run() EXIT "+ getName()+", exception: "+error); } if(null!=error) { throw error; diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index a0bbcc264..b10561c5b 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -355,24 +355,39 @@ public abstract class DisplayImpl extends Display { DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable(); final void dispatchMessage(final NEWTEventTask eventTask) { - NEWTEvent event = eventTask.get(); - if(null == event) { - // Ooops ? - System.err.println("Warning: event of eventTask is NULL"); - Thread.dumpStack(); - return; - } - Object source = event.getSource(); - if(source instanceof NEWTEventConsumer) { - NEWTEventConsumer consumer = (NEWTEventConsumer) source ; - if(!consumer.consumeEvent(event)) { - // enqueue for later execution - enqueueEvent(false, event); + final NEWTEvent event = eventTask.get(); + try { + if(null == event) { + // Ooops ? + System.err.println("Warning: event of eventTask is NULL"); + Thread.dumpStack(); + return; + } + final Object source = event.getSource(); + if(source instanceof NEWTEventConsumer) { + final NEWTEventConsumer consumer = (NEWTEventConsumer) source ; + if(!consumer.consumeEvent(event)) { + // enqueue for later execution + enqueueEvent(false, event); + } + } else { + throw new RuntimeException("Event source not NEWT: "+source.getClass().getName()+", "+source); + } + } catch (Throwable t) { + final RuntimeException re; + if(t instanceof RuntimeException) { + re = (RuntimeException) t; + } else { + re = new RuntimeException(t); + } + if( eventTask.isCallerWaiting() ) { + // propagate exception to caller + eventTask.setException(re); + } else { + throw re; } - } else { - throw new RuntimeException("Event source not NEWT: "+source.getClass().getName()+", "+source); } - eventTask.notifyIssuer(); + eventTask.notifyCaller(); } public void dispatchMessages() { @@ -423,8 +438,8 @@ public abstract class DisplayImpl extends Display { return; } - Object lock = new Object(); - NEWTEventTask eTask = new NEWTEventTask(e, wait?lock:null); + final Object lock = new Object(); + final NEWTEventTask eTask = new NEWTEventTask(e, wait?lock:null); synchronized(lock) { synchronized(eventsLock) { events.add(eTask); @@ -437,7 +452,10 @@ public abstract class DisplayImpl extends Display { } catch (InterruptedException ie) { throw new RuntimeException(ie); } - } + if( null != eTask.getException() ) { + throw eTask.getException(); + } + } } } diff --git a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java index fae6560b4..93d5e2fb9 100644 --- a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java +++ b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java @@ -35,17 +35,22 @@ import com.jogamp.newt.event.NEWTEvent; * which notifies after sending the event for the invokeAndWait() semantics. */ public class NEWTEventTask { - NEWTEvent event; - Object notifyObject; + private NEWTEvent event; + private Object notifyObject; + private RuntimeException exception; public NEWTEventTask(NEWTEvent event, Object notifyObject) { this.event = event ; this.notifyObject = notifyObject ; + this.exception = null; } - public NEWTEvent get() { return event; } + public final NEWTEvent get() { return event; } + public final void setException(RuntimeException e) { exception = e; } + public final RuntimeException getException() { return exception; } + public final boolean isCallerWaiting() { return null != notifyObject; } - public void notifyIssuer() { + public void notifyCaller() { if(null != notifyObject) { synchronized (notifyObject) { notifyObject.notifyAll(); -- cgit v1.2.3