/* * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, * and the EPL 1.0 (http://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.test.utils; import java.sql.Timestamp; import java.util.Map; /** * This is a self-destructor class to kill a long running process automatically * after a pre-defined time. The class reads the number of minutes from the * system property 'h2.selfDestruct' and starts a countdown thread to kill the * virtual machine if it still runs then. */ public class SelfDestructor { private static final String PROPERTY_NAME = "h2.selfDestruct"; /** * Start the countdown. If the self-destruct system property is set, this * value is used, otherwise the given default value is used. * * @param defaultMinutes the default number of minutes after which the * current process is killed. */ public static void startCountdown(int defaultMinutes) { final int minutes = Integer.parseInt( System.getProperty(PROPERTY_NAME, "" + defaultMinutes)); if (minutes == 0) { return; } Thread thread = new Thread() { @Override public void run() { for (int i = minutes; i >= 0; i--) { while (true) { try { String name = "SelfDestructor " + i + " min"; setName(name); break; } catch (OutOfMemoryError e) { // ignore } } try { Thread.sleep(60 * 1000); } catch (InterruptedException e) { // ignore } } try { String time = new Timestamp( System.currentTimeMillis()).toString(); System.out.println(time + " Killing the process after " + minutes + " minute(s)"); try { Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces(); for (Map.Entry<Thread, StackTraceElement[]> en : map.entrySet()) { System.out.println(en.getKey()); for (StackTraceElement el : en.getValue()) { System.out.println(" " + el); } } System.out.println(); System.out.flush(); try { Thread.sleep(1000); } catch (Exception e) { // ignore } int activeCount = Thread.activeCount(); Thread[] threads = new Thread[activeCount + 100]; int len = Thread.enumerate(threads); for (int i = 0; i < len; i++) { Thread t = threads[i]; if (t != Thread.currentThread()) { t.interrupt(); } } } catch (Throwable t) { t.printStackTrace(); // ignore } try { Thread.sleep(1000); } catch (Exception e) { // ignore } System.out.println("Killing the process now"); } catch (Throwable t) { try { t.printStackTrace(System.out); } catch (Throwable t2) { // ignore (out of memory) } } Runtime.getRuntime().halt(1); } }; thread.setDaemon(true); thread.start(); } /** * Get the string to be added when starting the Java process. * * @param minutes the countdown time in minutes * @return the setting */ public static String getPropertyString(int minutes) { return "-D" + PROPERTY_NAME + "=" + minutes; } }