[java] Fix non-termination when main/2 throws an exception

When main/2 throws an exception we did not properly shutdown the thread pool
and therefore the JVM would not shut down.  Simply calling shutdown() in a
finally block is insufficient because then the primordial thread may finish
before the worker thread is able to report the exception thrown by main/2.
This doesn't seem right because the JVM is supposed to wait for all the
non-daemon threads to finish before it exits.  I suspect that the primordial
thread is closing stdout and stderr as it exits and therefore the exception
is never seen, but I don't know.

This change fixes the issue by ensuring that shutdown() is always called (in
a finally block) and that the main thread waits for the thread pool to
shutdown before it exits.

java/runtime/MercuryThreadPool.java:
    runMain() will not exit until the worker threads have exited.

    Create a new method waitForShutdown() that will wait for the thread pool
    to shutdown.

    Signal the main thread when a worker thread exits.

java/runtime/MercuryWorkerThread.java:
    Worker threads now exit if their task raises an unhanded exception.

java/runtime/MercuryRuntime.java:
    Allow standalone programs to have the same behavour as programs whose
    entrypoint is written in Mercury.
This commit is contained in:
Paul Bone
2014-12-30 12:24:03 +11:00
parent f0a1701bc8
commit 5c4671ce9b
3 changed files with 82 additions and 14 deletions

View File

@@ -59,6 +59,8 @@ public class MercuryWorkerThread extends MercuryThread
// The task threw a Mercury exception.
pool.taskFailed(task, e);
JavaInternal.reportUncaughtException(e);
// Make the thread exit after throwing an exception.
break;
} catch (Throwable e) {
// Some other error occured. bail out.
System.err.println("Uncaught exception: " + e.toString());