From b5147c8b0ded2a81ac73791177deb5c056dd23c9 Mon Sep 17 00:00:00 2001 From: Wolfgang Schell Date: Thu, 21 Jul 2011 01:37:33 +0200 Subject: [PATCH] Ensure clean shutdown without calling System.exit(). Note: it is currently not possible to restart Erjang without reloading the classes, as some (static) objects need to be re-created: ERT.scheduler, ERT.async_scheduler, ETimerTask.send_timer --- src/main/java/erjang/ERT.java | 9 ++++- src/main/java/erjang/ETimerTask.java | 5 +++ src/main/java/erjang/Main.java | 3 +- src/main/java/erjang/OTPMain.java | 9 ++++- src/main/java/erjang/console/ERLConsole.java | 31 +++++++++-------- src/main/java/erjang/driver/EDriverTask.java | 1 - src/main/java/erjang/m/erlang/ErlProc.java | 35 ++++++++++++-------- 7 files changed, 61 insertions(+), 32 deletions(-) diff --git a/src/main/java/erjang/ERT.java b/src/main/java/erjang/ERT.java index f7bfd0fd..7c3de9e3 100644 --- a/src/main/java/erjang/ERT.java +++ b/src/main/java/erjang/ERT.java @@ -1041,6 +1041,14 @@ public static void shutdown() { init_pid.sendb(tup); } } + + /** + * Shutdown Kilim schedulers. + */ + /*package*/ static void shutdownSchedulers() { + scheduler.shutdown(); + async_scheduler.shutdown(); + } static public InputStream orig_in = System.in; static public PrintStream orig_out = System.out; @@ -1069,5 +1077,4 @@ public static void debug(boolean condition, String text) { debug(text); } } - } diff --git a/src/main/java/erjang/ETimerTask.java b/src/main/java/erjang/ETimerTask.java index ecdaf400..cf250ff4 100644 --- a/src/main/java/erjang/ETimerTask.java +++ b/src/main/java/erjang/ETimerTask.java @@ -134,4 +134,9 @@ public static long read_timer(ERef ref) { return -1; } + + public static void shutdown() { + send_timer.cancel(); + send_timer.purge(); + } } diff --git a/src/main/java/erjang/Main.java b/src/main/java/erjang/Main.java index c27e9ecd..ea0a4e61 100644 --- a/src/main/java/erjang/Main.java +++ b/src/main/java/erjang/Main.java @@ -84,7 +84,6 @@ private static String guess_erl_root() { ERT.log.severe("Cannot find OTPROOT directory\n" + "Pass -root , or set environment variable."); - System.exit(-1); return null; } @@ -162,7 +161,7 @@ public static void main(String[] args) throws Exception { if (!(new File(erl_bootstrap_ebindir)).exists() && !erl_bootstrap_ebindir.startsWith(EFile.RESOURCE_PREFIX)) { ERT.log.severe("No bootstrap classes at: "+erl_bootstrap_ebindir); - System.exit(1); + throw new IllegalArgumentException("No bootstrap classes at: "+erl_bootstrap_ebindir); } OTPMain.main(ra.toArray(new String[ra.size()])); diff --git a/src/main/java/erjang/OTPMain.java b/src/main/java/erjang/OTPMain.java index 3898b155..ad54158e 100644 --- a/src/main/java/erjang/OTPMain.java +++ b/src/main/java/erjang/OTPMain.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.logging.FileHandler; import java.util.logging.Handler; -import java.util.logging.Level; import java.util.logging.Logger; import erjang.driver.EDriver; @@ -83,10 +82,18 @@ public static void start_otp_ring0(ESeq argv) { EAtom am_start = EAtom.intern("start"); ESeq env = ERT.NIL; + // launch first (initial) process, which starts OTP EProc proc = new EProc(null, am_otp_ring0, am_start, ERT.NIL.cons(argv).cons(env)); ERT.run(proc); + + // wait for this process to terminate proc.joinb(); + + // shutdown schedulers, after the first (initial) process has stopped + ERT.shutdownSchedulers(); + // shutdown timer task + ETimerTask.shutdown(); } protected static ESeq process_args(String[] args) { diff --git a/src/main/java/erjang/console/ERLConsole.java b/src/main/java/erjang/console/ERLConsole.java index 5adf3689..09589337 100644 --- a/src/main/java/erjang/console/ERLConsole.java +++ b/src/main/java/erjang/console/ERLConsole.java @@ -56,7 +56,7 @@ public ERLConsole(String title) { static final int HINSET = 8; public static void main(final String[] args) { - final ERLConsole console = new ERLConsole("Erjang Console"); + ERLConsole console = new ERLConsole("Erjang Console"); console.getContentPane().setLayout(new BorderLayout()); console.setSize(700, 600); @@ -77,7 +77,7 @@ public static void main(final String[] args) { pane.setBorder(BorderFactory.createLineBorder(Color.darkGray)); console.getContentPane().add(pane, BorderLayout.CENTER); - StatusBar status = new StatusBar(); + final StatusBar status = new StatusBar(); console.getContentPane().add(status, BorderLayout.SOUTH); console.validate(); @@ -88,12 +88,20 @@ public void windowClosing(WindowEvent e) { ERT.shutdown(); } }); + console.setVisible(true); + + Timer timer = new Timer(true); + timer.schedule(new TimerTask() { + + @Override + public void run() { + status.updateMemory(); + }}, 1000, 1000); erjang.OTPMain.add_driver(tty); Thread t2 = new Thread() { public void run() { - console.setVisible(true); try { erjang.Main.main(args); } catch (Exception e) { @@ -108,8 +116,12 @@ public void run() { } catch (InterruptedException ie) { // ignore } - - System.exit(0); + timer.cancel(); + timer.purge(); + timer = null; + console.setVisible(false); + console.dispose(); + console = null; } private Font findFont(String otherwise, int style, int size, String[] families) { @@ -138,7 +150,7 @@ private Font findFont(String otherwise, int style, int size, String[] families) @SuppressWarnings("serial") class StatusBar extends JPanel { - private JLabel mem_label; + private JLabel mem_label; private JLabel progress; public StatusBar() { @@ -168,13 +180,6 @@ public void run() { mem_label = new JLabel(); add(mem_label, BorderLayout.CENTER); - - new Timer(true).schedule(new TimerTask() { - - @Override - public void run() { - StatusBar.this.updateMemory(); - }}, 1000, 1000); } void updateMemory() { diff --git a/src/main/java/erjang/driver/EDriverTask.java b/src/main/java/erjang/driver/EDriverTask.java index 64699212..4aa26480 100644 --- a/src/main/java/erjang/driver/EDriverTask.java +++ b/src/main/java/erjang/driver/EDriverTask.java @@ -351,7 +351,6 @@ public void execute() throws Pausable { if (log.isLoggable(Level.FINER)) { log.finer("EXITING "+result); - System.exit(1); } } finally { diff --git a/src/main/java/erjang/m/erlang/ErlProc.java b/src/main/java/erjang/m/erlang/ErlProc.java index 3fef62ec..6509efbf 100644 --- a/src/main/java/erjang/m/erlang/ErlProc.java +++ b/src/main/java/erjang/m/erlang/ErlProc.java @@ -271,28 +271,35 @@ public static EObject spawn(EProc proc, EObject mod, EObject fun, EObject args) @BIF public static EObject halt(EProc proc) { - System.exit(0); - return null; + return halt(proc, null); } @BIF public static EObject halt(EProc proc, EObject value) { - ESmall val = value.testSmall(); - if (val != null) { - System.exit(val.value); - return null; + int exitCode = 1; + String message = null; + if (value != null) { + ESmall val = value.testSmall(); + if (val != null) { + exitCode = val.value; + } + + EString str = value.testString(); + if (str != null) { + message = str.stringValue(); + } } - EString str = value.testString(); - if (str != null) { - // TODO: create crash file - log.severe("halting system: " + str.stringValue()); - System.exit(1); + // TODO: create crash file + if (message != null) { + log.severe("halting system: " + message); } + else { + log.info("halting system"); + } + ERT.shutdown(); - throw ERT.badarg(value); - - + return null; } @BIF