mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
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.
147 lines
4.4 KiB
Java
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);
|
|
}
|
|
}
|