Files
mercury/java/runtime/JavaInternal.java
Julien Fischer 89293d8faa Add MercuryFatalError exception to the Java runtime.
Add MercuryFatalError, a new Java exception that is intended to be used for a
similar purpose to the C runtime's MR_fatal_error() function.

Throw a MercuryFatalError exception instead of calling System.exit() in a spot.
Calling exit() is fine for executables, but for code that is deployed in an
application server calling exit() may shut down the entire server.

java/runtime/MercuryFatalError.java:
    Add the new exception.

java/runtime/MercuryOptions.java:
    Do not call System.exit() when we encounter an unrecognized
    option in MERCURY_OPTIONS, throw a MercuryFatalError exception
    instead.

    Refactor the process() method in order to avoid indentation.

    Catch NumberFormatExceptions thrown when attempting to convert
    integer option values; rethrow them as MercuryFatalErrors.
    (XXX the C version of the runtime just ignores this error.)

java/runtime/JavaInternal.java:
    Catch and report MercuryFatalErrors in the runMain() method.

java/runtime/MercuryWorkerThread.java:
    Add an XXX about a call to System.exit() here.
2024-01-19 21:57:20 +11:00

147 lines
4.4 KiB
Java

// vim: ts=4 sw=4 expandtab ft=java
//
// Copyright (C) 2001-2003, 2009 The University of Melbourne.
// Copyright (C) 2014, 2017-2018 The Mercury Team.
// This file is distributed under the terms specified in COPYING.LIB.
//
// All modifications to this file will require changes to:
// compiler/mlds_to_java.m
package jmercury.runtime;
/**
* Internals and static objects for Mercury's runtime system on the Java
* backend.
* This class is used to store the main module's name (progname), command
* line arguments and the exit status. We can't put them in one of the
* library modules because we need to hold them in a class variable in a top
* level class.
*
* The class also contains utility methods and other objects such as a
* reference to the thread pool.
*
* No instance of this class is ever created, all of its members and methods
* are static.
*/
public class JavaInternal {
/**
* 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 JavaInternal() {
}
private static MercuryThreadPool thread_pool = null;
private static MercuryOptions options = null;
public static synchronized MercuryThreadPool getThreadPool() {
if (thread_pool == null) {
thread_pool = new MercuryThreadPool(
getOptions().getNumProcessors());
}
return thread_pool;
}
public static synchronized MercuryOptions getOptions() {
if (options == null) {
options = new MercuryOptions();
options.process();
}
return options;
}
public static java.lang.String progname;
public static java.lang.String[] args;
public static int exit_status;
private static ExceptionReporter exception_reporter;
private static java.util.List<Runnable> finalisers
= new java.util.ArrayList<Runnable>();
public static void register_finaliser(Runnable hook) {
finalisers.add(hook);
}
public static void run_finalisers() {
for (Runnable r : finalisers) {
r.run();
}
}
/**
* Run the main task.
* The main task is executed by the thread pool so that when it blocks
* the thread pool is notified correctly.
*/
public static void runMain(Runnable main)
{
try {
getThreadPool().runMain(main);
} catch (jmercury.runtime.MercuryFatalError e) {
System.out.flush();
System.err.println("Mercury runtime: " + e.getMessage());
System.err.flush();
if (exit_status == 0) {
exit_status = 1;
}
}
}
/**
* Set the exception reporter if one is not set already.
* The specified object will be used by reportUncaughtException to
* report exceptions. See the comment for reportUncaughtException()
% @param reporter The new exception reporter object.
*/
public static void setExceptionReporter(ExceptionReporter reporter)
{
if (null == exception_reporter) {
exception_reporter = reporter;
}
}
/**
* Report uncaught exceptions.
* This reports exceptions using the exception reporter object, if it is
* set. Otherwise we make a best effort at reporting it.
*
* Exception reporting code is written in exception.m which we cannot
* link to from here. When that code starts it should set an exception
* reporter object.
*/
public static void reportUncaughtException(jmercury.runtime.Exception e)
{
if (null != exception_reporter) {
exception_reporter.reportUncaughtException(e);
} else {
System.out.flush();
System.err.println("Uncaught exception: " + e.getMessage());
System.err.flush();
}
if (shouldPrintStackTrace()) {
e.printStackTrace(System.err);
}
if (exit_status == 0) {
exit_status = 1;
}
}
/**
* Should we print Java stack traces when we catch Mercury exceptions?
*/
public static boolean shouldPrintStackTrace() {
return System.getenv("MERCURY_SUPPRESS_STACK_TRACE") == null;
}
/**
* Interface for reporting exceptions.
*/
public interface ExceptionReporter {
public void reportUncaughtException(jmercury.runtime.Exception e);
}
}