From fceb13bf732d1e61fd7140aa06be728483473a78 Mon Sep 17 00:00:00 2001 From: Jakub Valtar Date: Thu, 29 Dec 2016 17:04:16 +0100 Subject: [PATCH] FX: Add exception handler which reports exceptions form user code Fixes #4339 --- core/src/processing/javafx/PSurfaceFX.java | 44 +++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/core/src/processing/javafx/PSurfaceFX.java b/core/src/processing/javafx/PSurfaceFX.java index 9cd5baa11..f7e08d8a4 100644 --- a/core/src/processing/javafx/PSurfaceFX.java +++ b/core/src/processing/javafx/PSurfaceFX.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.SynchronousQueue; import javafx.animation.Animation; import javafx.animation.KeyFrame; @@ -71,6 +72,8 @@ public class PSurfaceFX implements PSurface { final Animation animation; float frameRate = 60; + private SynchronousQueue drawExceptionQueue = new SynchronousQueue<>(); + public PSurfaceFX(PGraphicsFX2D graphics) { fx = graphics; canvas = new ResizableCanvas(); @@ -80,7 +83,16 @@ public class PSurfaceFX implements PSurface { new EventHandler() { public void handle(ActionEvent event) { long startNanoTime = System.nanoTime(); - sketch.handleDraw(); + try { + sketch.handleDraw(); + } catch (Throwable e) { + // Let exception handler thread crash with our exception + drawExceptionQueue.offer(e); + // Stop animating right now so nothing runs afterwards + // and crash frame can be for example traced by println() + animation.stop(); + return; + } long drawNanos = System.nanoTime() - startNanoTime; if (sketch.exitCalled()) { @@ -366,10 +378,40 @@ public class PSurfaceFX implements PSurface { } catch (InterruptedException e) { } } + startExceptionHandlerThread(); + setProcessingIcon(stage); } + private void startExceptionHandlerThread() { + Thread exceptionHandlerThread = new Thread(() -> { + Throwable drawException; + try { + drawException = drawExceptionQueue.take(); + } catch (InterruptedException e) { + return; + } + // Adapted from PSurfaceJOGL + if (drawException != null) { + if (drawException instanceof ThreadDeath) { +// System.out.println("caught ThreadDeath"); +// throw (ThreadDeath)cause; + } else if (drawException instanceof RuntimeException) { + throw (RuntimeException) drawException; + } else if (drawException instanceof UnsatisfiedLinkError) { + throw new UnsatisfiedLinkError(drawException.getMessage()); + } else { + throw new RuntimeException(drawException); + } + } + }); + exceptionHandlerThread.setDaemon(true); + exceptionHandlerThread.setName("Processing-FX-ExceptionHandler"); + exceptionHandlerThread.start(); + } + + /** Set the window (and dock, or whatever necessary) title. */ public void setTitle(String title) { // PApplicationFX.title = title; // store this in case the stage still null