Skip to content

Commit 05e80cb

Browse files
committed
Monitor the worker process to ensure things are OK
If the worker process crashes, pending tasks should crash out, not hang.
1 parent bd4f556 commit 05e80cb

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

src/main/java/org/apposed/appose/Service.java

+36-4
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public class Service implements AutoCloseable {
6262
private PrintWriter stdin;
6363
private Thread stdoutThread;
6464
private Thread stderrThread;
65+
private Thread monitorThread;
6566

6667
private Consumer<String> debugListener;
6768

@@ -99,8 +100,10 @@ public Service start() throws IOException {
99100
stdin = new PrintWriter(process.getOutputStream());
100101
stdoutThread = new Thread(this::stdoutLoop, prefix + "-Stdout");
101102
stderrThread = new Thread(this::stderrLoop, prefix + "-Stderr");
103+
monitorThread = new Thread(this::monitorLoop, prefix + "-Monitor");
102104
stderrThread.start();
103105
stdoutThread.start();
106+
monitorThread.start();
104107
return this;
105108
}
106109

@@ -194,6 +197,35 @@ private void stderrLoop() {
194197
}
195198
}
196199

200+
private void monitorLoop() {
201+
// Wait until the worker process terminates.
202+
while (process.isAlive()) {
203+
try {
204+
Thread.sleep(50);
205+
}
206+
catch (InterruptedException exc) {
207+
debugService(Types.stackTrace(exc));
208+
}
209+
}
210+
211+
// Do some sanity checks.
212+
int exitCode = process.exitValue();
213+
if (exitCode != 0) debugService("<worker process terminated with exit code " + exitCode + ">");
214+
int taskCount = tasks.size();
215+
if (taskCount > 0) debugService("<worker process terminated with " + taskCount + " pending tasks>");
216+
217+
// Notify any remaining tasks about the process crash.
218+
for (Task task : tasks.values()) {
219+
TaskEvent event = new TaskEvent(task, ResponseType.CRASH);
220+
task.status = TaskStatus.CRASHED;
221+
task.listeners.forEach(l -> l.accept(event));
222+
synchronized (task) {
223+
task.notifyAll();
224+
}
225+
}
226+
tasks.clear();
227+
}
228+
197229
private void debugService(String message) { debug("SERVICE", message); }
198230
private void debugWorker(String message) { debug("WORKER", message); }
199231

@@ -207,13 +239,13 @@ private void debug(String prefix, String message) {
207239
}
208240

209241
public enum TaskStatus {
210-
INITIAL, QUEUED, RUNNING, COMPLETE, CANCELED, FAILED;
242+
INITIAL, QUEUED, RUNNING, COMPLETE, CANCELED, FAILED, CRASHED;
211243

212244
/**
213-
* @return true iff status is {@link #COMPLETE}, {@link #CANCELED}, or {@link #FAILED}.
245+
* @return true iff status is {@link #COMPLETE}, {@link #CANCELED}, {@link #FAILED}, or {@link #CRASHED}.
214246
*/
215247
public boolean isFinished() {
216-
return this == COMPLETE || this == CANCELED || this == FAILED;
248+
return this == COMPLETE || this == CANCELED || this == FAILED || this == CRASHED;
217249
}
218250
}
219251

@@ -222,7 +254,7 @@ public enum RequestType {
222254
}
223255

224256
public enum ResponseType {
225-
LAUNCH, UPDATE, COMPLETION, CANCELATION, FAILURE
257+
LAUNCH, UPDATE, COMPLETION, CANCELATION, FAILURE, CRASH
226258
}
227259

228260
/**

src/test/java/org/apposed/appose/ApposeTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ class TaskState {
114114
task.waitFor();
115115

116116
// Validate the execution result.
117+
assertSame(TaskStatus.COMPLETE, task.status);
117118
Number result = (Number) task.outputs.get("result");
118119
assertEquals(91, result.intValue());
119120

0 commit comments

Comments
 (0)