Files
mercury/java/runtime/MercuryRuntime.java
Paul Bone 5c4671ce9b [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.
2014-12-30 17:07:35 +11:00

65 lines
1.7 KiB
Java

//
// Copyright (C) 2014 The Mercury Team
// This file may only be copied under the terms of the GNU Library General
// Public License - see the file COPYING.LIB in the Mercury distribution.
//
package jmercury.runtime;
/**
* Interface to the Mercury Runtime System for Java code.
*
* No instance of this class is ever created, all its members and methods
* are static.
*/
public class MercuryRuntime
{
/**
* Private constructor.
* This private constructor doesn't do anything and isn't called by
* anyone. It exists only to prevent people from creating an instance.
*/
private MercuryRuntime() {
}
private static MercuryThreadPool thread_pool = null;
/**
* Return the thread pool, initialising it if required.
* This does not start the thread pool. It is started either when
* startup() is called or automatically when the first task is
* submitted.
*/
public static synchronized MercuryThreadPool getThreadPool()
{
if (thread_pool == null) {
thread_pool = new MercuryThreadPool(
JavaInternal.getOptions().getNumProcessors());
}
return thread_pool;
}
/**
* Retrieve the exit status stored in the I/O state.
*/
public static int getExitStatus() {
return JavaInternal.exit_status;
}
/**
* Finalise the runtime system.
* This _must_ be called at the normal end of any program. It runs
* finalisers and stops the thread pool.
* This will wait for the thread pool to shutdown.
*/
public static void finalise() {
MercuryThreadPool pool;
pool = getThreadPool();
JavaInternal.run_finalisers();
pool.shutdown();
pool.waitForShutdown();
}
}