changeset 1086:d15ebde32b25

7901244: Forceful shutdown of forked VM when there are uncontrollable user threads Summary: Implement a shutdown timeout.
author shade
date Tue, 13 Jan 2015 12:32:02 +0300
parents 723dc85eb157
children 127f9a76e58f
files jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java jmh-core/src/main/java/org/openjdk/jmh/runner/ForkedMain.java
diffstat 2 files changed, 43 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java	Mon Jan 12 23:41:06 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java	Tue Jan 13 12:32:02 2015 +0300
@@ -163,7 +163,9 @@
                 Reader reader = destination.getResource(BenchmarkList.BENCHMARK_LIST.substring(1));
                 Collection<String> existingLines = FileUtils.readAllLines(reader);
                 for (String line : existingLines) {
-                    entries.add(new BenchmarkListEntry(line));
+                    BenchmarkListEntry br = new BenchmarkListEntry(line);
+                    entries.add(br);
+                    destination.printWarning("Old benchmark: " + br);
                 }
             } catch (IOException e) {
                 // Expected in most cases, move on.
@@ -204,6 +206,8 @@
                         if (entries.contains(br)) {
                             destination.printWarning("Benchmark entry " + br + " already exists, overwriting");
                             entries.remove(br);
+                        } else {
+                            destination.printWarning("New benchmark: " + br);
                         }
 
                         entries.add(br);
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/ForkedMain.java	Mon Jan 12 23:41:06 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/ForkedMain.java	Tue Jan 13 12:32:02 2015 +0300
@@ -24,10 +24,12 @@
  */
 package org.openjdk.jmh.runner;
 
+import org.openjdk.jmh.infra.ThreadParams;
 import org.openjdk.jmh.runner.link.BinaryLinkClient;
 import org.openjdk.jmh.runner.options.Options;
 
 import java.io.IOException;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Main program entry point for forked JVM instance
@@ -68,6 +70,9 @@
                 runner.run();
 
                 gracefullyFinished = true;
+
+                // arm the shutdown timer
+                new ShutdownTimeoutThread(link).start();
             } catch (Throwable ex) {
                 exception = ex;
                 System.exit(1);
@@ -75,6 +80,39 @@
         }
     }
 
+    private static class ShutdownTimeoutThread extends Thread {
+        private static final int TIMEOUT = Integer.getInteger("jmh.shutdownTimeout", 30);
+        private static final int TIMEOUT_STEP = Integer.getInteger("jmh.shutdownTimeout.step", 5);
+        private final BinaryLinkClient link;
+
+        public ShutdownTimeoutThread(final BinaryLinkClient link) {
+            this.link = link;
+            setName("JMH-Shutdown-Timeout");
+            setDaemon(true);
+        }
+
+        @Override
+        public void run() {
+            long start = System.nanoTime();
+
+            long waitMore;
+            do {
+                try {
+                    TimeUnit.SECONDS.sleep(TIMEOUT_STEP);
+                } catch (InterruptedException e) {
+                    return;
+                }
+
+                waitMore = TimeUnit.SECONDS.toNanos(TIMEOUT) - (System.nanoTime() - start);
+                link.getOutputFormat().println("<JMH had finished, but forked VM did not exit, are there stray running threads? Waiting " +
+                        TimeUnit.NANOSECONDS.toSeconds(waitMore) + " seconds more...>");
+            } while (waitMore > 0);
+
+            link.getOutputFormat().println("<shutdown timeout of " + TIMEOUT + " seconds expired, forcing forked VM to exit>");
+            System.exit(0);
+        }
+    }
+
     private static void addShutdownHook(final BinaryLinkClient link) {
         Runtime.getRuntime().addShutdownHook(
                 new Thread() {