Skip to content

Commit eef83e5

Browse files
committed
*: Add exception handler
Signed-off-by: Ce Gao <[email protected]>
1 parent a140dce commit eef83e5

File tree

4 files changed

+114
-31
lines changed

4 files changed

+114
-31
lines changed

src/rprocessing/RLangPApplet.java

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.awt.Window;
55
import java.awt.event.ComponentAdapter;
66
import java.awt.event.ComponentEvent;
7+
import java.lang.Thread.UncaughtExceptionHandler;
78
import java.lang.reflect.Method;
89
import java.util.Arrays;
910
import java.util.concurrent.CountDownLatch;
@@ -12,6 +13,7 @@
1213
import javax.script.ScriptEngineManager;
1314
import javax.script.ScriptException;
1415

16+
import org.renjin.eval.EvalException;
1517
import org.renjin.parser.RParser;
1618
import org.renjin.script.RenjinScriptEngine;
1719
import org.renjin.sexp.Closure;
@@ -20,8 +22,6 @@
2022
import org.renjin.sexp.SEXP;
2123
import org.renjin.sexp.Symbol;
2224

23-
import com.jogamp.newt.opengl.GLWindow;
24-
2525
import processing.awt.PSurfaceAWT;
2626
import processing.core.PApplet;
2727
import processing.core.PConstants;
@@ -30,10 +30,13 @@
3030
import processing.opengl.PSurfaceJOGL;
3131
import rprocessing.applet.BuiltinApplet;
3232
import rprocessing.exception.NotFoundException;
33+
import rprocessing.exception.RSketchError;
3334
import rprocessing.util.Constant;
3435
import rprocessing.util.Printer;
3536
import rprocessing.util.RScriptReader;
3637

38+
import com.jogamp.newt.opengl.GLWindow;
39+
3740
/**
3841
* RlangPApplet PApplet for R language, powered by Renjin.
3942
*
@@ -61,6 +64,8 @@ public class RLangPApplet extends BuiltinApplet {
6164

6265
private final CountDownLatch finishedLatch = new CountDownLatch(1);
6366

67+
private RSketchError terminalException = null;
68+
6469
/**
6570
* Mode for Processing.
6671
*
@@ -144,7 +149,7 @@ public void addPAppletToRContext() {
144149
this.renjinEngine.put("stdout", stdout);
145150
}
146151

147-
public void runBlock(final String[] arguments) {
152+
public void runBlock(final String[] arguments) throws RSketchError {
148153
log("runBlock");
149154
PApplet.runSketch(arguments, this);
150155
try {
@@ -161,8 +166,7 @@ public void runBlock(final String[] arguments) {
161166
}
162167
} finally {
163168
Thread.setDefaultUncaughtExceptionHandler(null);
164-
if (PApplet.platform == PConstants.MACOSX
165-
&& Arrays.asList(arguments).contains("fullScreen")) {
169+
if (PApplet.platform == PConstants.MACOSX && Arrays.asList(arguments).contains("fullScreen")) {
166170
// Frame should be OS-X fullscreen, and it won't stop being that unless the jvm
167171
// exits or we explicitly tell it to minimize.
168172
// (If it's disposed, it'll leave a gray blank window behind it.)
@@ -182,9 +186,9 @@ public void runBlock(final String[] arguments) {
182186
surface.setVisible(false);
183187
}
184188
}
185-
// if (terminalException != null) {
186-
// throw terminalException;
187-
// }
189+
if (terminalException != null) {
190+
throw terminalException;
191+
}
188192
}
189193

190194
private static void macosxFullScreenToggle(final Window window) {
@@ -242,6 +246,28 @@ public void exitActual() {
242246
finishedLatch.countDown();
243247
}
244248

249+
/**
250+
* @see processing.core.PApplet#start()
251+
*/
252+
@Override
253+
public void start() {
254+
// I want to quit on runtime exceptions.
255+
// Processing just sits there by default.
256+
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
257+
@Override
258+
public void uncaughtException(final Thread t, final Throwable e) {
259+
terminalException = toSketchException(e);
260+
try {
261+
handleMethods("dispose");
262+
} catch (final Exception noop) {
263+
// give up
264+
}
265+
finishedLatch.countDown();
266+
}
267+
});
268+
super.start();
269+
}
270+
245271
/**
246272
* @see processing.core.PApplet#settings()
247273
*/
@@ -270,7 +296,8 @@ public void setup() {
270296
try {
271297
this.renjinEngine.eval(this.programText);
272298
} catch (ScriptException exception) {
273-
log(exception.toString());
299+
terminalException = toSketchException(exception);
300+
exitActual();
274301
}
275302
} else if (this.mode == Mode.ACTIVE) {
276303
Object obj = this.renjinEngine.get(Constant.SETUP_NAME);
@@ -348,4 +375,19 @@ protected void wrapProcessingVariables() {
348375
private static boolean isSameClass(Object obj, Class clazz) {
349376
return obj.getClass().equals(clazz);
350377
}
378+
379+
private static RSketchError toSketchException(Throwable t) {
380+
if (t instanceof RuntimeException && t.getCause() != null) {
381+
t = t.getCause();
382+
}
383+
if (t instanceof RSketchError) {
384+
return (RSketchError) t;
385+
}
386+
if (t instanceof EvalException) {
387+
final RSketchError e = (RSketchError) t;
388+
return e;
389+
}
390+
log("No exception type detected.");
391+
return null;
392+
}
351393
}

src/rprocessing/Runner.java

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
import javax.script.ScriptException;
44

5-
import org.renjin.eval.EvalException;
65

76
import rprocessing.exception.NotFoundException;
8-
import rprocessing.exception.REvalException;
7+
import rprocessing.exception.RSketchError;
98
import rprocessing.lancher.StandaloneSketch;
109
import rprocessing.util.Printer;
1110
import rprocessing.util.StreamPrinter;
@@ -18,6 +17,8 @@
1817
public class Runner {
1918

2019
public static RunnableSketch sketch;
20+
private static final String CORE_TEXT =
21+
RScriptReader.readResourceAsText(Runner.class, "r/core.R");
2122

2223
private static final boolean VERBOSE = Boolean.parseBoolean(System.getenv("VERBOSE_RLANG_MODE"));
2324

@@ -49,29 +50,20 @@ public static void main(final String[] args) throws Exception {
4950
}
5051

5152
public static synchronized void runSketchBlocking(final RunnableSketch sketch,
52-
final Printer stdout, final Printer stderr)
53-
throws REvalException, NotFoundException, ScriptException {
53+
final Printer stdout, final Printer stderr) throws NotFoundException, RSketchError {
5454
runSketchBlocking(sketch, stdout, stderr, null);
5555
}
5656

5757
public static synchronized void runSketchBlocking(final RunnableSketch sketch,
5858
final Printer stdout, final Printer stderr,
59-
final SketchPositionListener sketchPositionListener)
60-
throws REvalException, NotFoundException, ScriptException {
59+
final SketchPositionListener sketchPositionListener) throws NotFoundException, RSketchError {
6160
final String[] args = sketch.getPAppletArguments();
6261

6362
log("Tring to initialize RLangPApplet.");
6463
RLangPApplet rp = new RLangPApplet(sketch.getMainCode(), stdout);
6564
log("Adding processing variable into R top context.");
6665
rp.addPAppletToRContext();
67-
rp.evaluateCoreCode();
6866

69-
try {
70-
// Run Sketch.
71-
rp.runBlock(args);
72-
log("Down");
73-
} catch (EvalException ee) {
74-
throw new REvalException(ee.getMessage());
75-
}
67+
rp.runBlock(args);
7668
}
7769
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package rprocessing.exception;
2+
3+
/**
4+
* Error type for Processing.R
5+
*
6+
* @author github.com/gaocegege
7+
*/
8+
public class RSketchError extends Exception {
9+
private static final long serialVersionUID = 6563629093797155634L;
10+
public final String fileName;
11+
public final int line;
12+
public final int column;
13+
14+
public RSketchError(final String message) {
15+
this(message, null);
16+
}
17+
18+
public RSketchError(final String message, final String fileName) {
19+
this(message, fileName, -1, -1);
20+
}
21+
22+
public RSketchError(final String message, final String fileName, final int line) {
23+
this(message, fileName, line, 0);
24+
}
25+
26+
public RSketchError(final String message, final String fileName, final int line, final int column) {
27+
super(message);
28+
29+
this.fileName = fileName;
30+
this.line = line;
31+
this.column = column;
32+
}
33+
34+
@Override
35+
public String toString() {
36+
if (fileName == null) {
37+
return getMessage();
38+
}
39+
if (line == -1) {
40+
return getMessage() + " in " + fileName;
41+
}
42+
if (column == -1) {
43+
return getMessage() + " at line " + line + " of " + fileName;
44+
}
45+
return getMessage() + " at " + line + ":" + column + " in " + fileName;
46+
}
47+
}

src/rprocessing/mode/run/SketchRunner.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import rprocessing.SketchPositionListener;
1111
import rprocessing.exception.REvalException;
1212
import rprocessing.exception.RMIRuntimeException;
13+
import rprocessing.exception.RSketchError;
1314
import rprocessing.mode.RLangMode;
1415
import rprocessing.mode.run.RMIUtils.RMIProblem;
1516
import rprocessing.util.Printer;
@@ -124,15 +125,16 @@ public void sketchMoved(final Point leftTop) {
124125
}
125126
}
126127
};
128+
log("Run the sketch.");
127129
Runner.runSketchBlocking(sketch, stdout, stderr, sketchPositionListener);
128-
} catch (final REvalException exception) {
130+
} catch (final RSketchError exception) {
129131
log("Sketch runner caught " + exception);
130-
modeService.handleSketchException(id,
131-
convertREvalError(exception, sketch.codeFileNames));
132+
modeService.handleSketchException(id, exception);
132133
} catch (final Exception exception) {
134+
log("Sketch runner caught Exception:" + exception);
133135
if (exception.getCause() != null && exception.getCause() instanceof REvalException) {
134136
modeService.handleSketchException(id,
135-
convertREvalError((REvalException) exception.getCause(), sketch.codeFileNames));
137+
convertREvalError((REvalException) exception.getCause()));
136138
} else {
137139
modeService.handleSketchException(id, exception);
138140
}
@@ -141,6 +143,7 @@ public void sketchMoved(final Point leftTop) {
141143
modeService.handleSketchStopped(id);
142144
}
143145
} catch (final RemoteException exception) {
146+
log("Sketch runner caught RemoteException:" + exception);
144147
log(exception.toString());
145148
}
146149
// Exiting; no need to interrupt and join it later.
@@ -225,8 +228,8 @@ private static void startSketchRunner(final String id) throws RMIRuntimeExceptio
225228
}
226229
}
227230

228-
private static void launch(final String id, final ModeService modeService)
229-
throws RMIProblem, RemoteException {
231+
private static void launch(final String id, final ModeService modeService) throws RMIProblem,
232+
RemoteException {
230233
final SketchRunner sketchRunner = new SketchRunner(id, modeService);
231234
final SketchService stub = (SketchService) RMIUtils.export(sketchRunner);
232235
log("Calling mode's handleReady().");
@@ -244,8 +247,7 @@ public void run() {
244247
}));
245248
}
246249

247-
private SketchException convertREvalError(final REvalException exception,
248-
final String[] fileNames) {
250+
private SketchException convertREvalError(final REvalException exception) {
249251
return new SketchException(exception.getMessage());
250252
}
251253
}

0 commit comments

Comments
 (0)