8034262: Test java/lang/ProcessBuilder/CloseRace.java fails
authorigerasim
Wed, 12 Mar 2014 21:45:20 +0400
changeset 23341 b9e3bcefc522
parent 23340 fe4b337b636e
child 23342 d7a41da68b85
8034262: Test java/lang/ProcessBuilder/CloseRace.java fails Reviewed-by: martin, dholmes
jdk/test/java/lang/ProcessBuilder/CloseRace.java
--- a/jdk/test/java/lang/ProcessBuilder/CloseRace.java	Wed Mar 12 08:55:35 2014 -0700
+++ b/jdk/test/java/lang/ProcessBuilder/CloseRace.java	Wed Mar 12 21:45:20 2014 +0400
@@ -33,6 +33,8 @@
 import java.io.*;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
 
 public class CloseRace {
     private static final String BIG_FILE = "bigfile";
@@ -43,6 +45,9 @@
     private static final int testDurationSeconds
         = Integer.getInteger("test.duration", 600);
 
+    private static final CountDownLatch threadsStarted
+        = new CountDownLatch(2);
+
     static boolean fdInUse(int i) {
         return new File("/proc/self/fd/" + i).exists();
     }
@@ -61,6 +66,18 @@
         return count;
     }
 
+    static void dumpAllStacks() {
+        System.err.println("Start of dump");
+        final Map<Thread, StackTraceElement[]> allStackTraces
+                = Thread.getAllStackTraces();
+        for (Thread thread : allStackTraces.keySet()) {
+            System.err.println("Thread " + thread.getName());
+            for (StackTraceElement element : allStackTraces.get(thread))
+                System.err.println("\t" + element);
+        }
+        System.err.println("End of dump");
+    }
+
     public static void main(String args[]) throws Exception {
         if (!(new File("/proc/self/fd").isDirectory()))
             return;
@@ -84,26 +101,41 @@
         for (Thread thread : threads)
             thread.start();
 
+        threadsStarted.await();
         Thread.sleep(testDurationSeconds * 1000);
 
         for (Thread thread : threads)
             thread.interrupt();
-        for (Thread thread : threads)
-            thread.join();
+        for (Thread thread : threads) {
+            thread.join(10_000);
+            if (thread.isAlive()) {
+                dumpAllStacks();
+                throw new Error("At least one child thread ("
+                        + thread.getName()
+                        + ") failed to finish gracefully");
+            }
+        }
     }
 
     static class OpenLoop implements Runnable {
         public void run() {
+            threadsStarted.countDown();
             while (!Thread.interrupted()) {
                 try {
                     // wait for ExecLoop to finish creating process
-                    do {} while (count(procFDsInUse()) != 3);
+                    do {
+                        if (Thread.interrupted())
+                            return;
+                    } while (count(procFDsInUse()) != 3);
                     List<InputStream> iss = new ArrayList<>(4);
 
                     // eat up three "holes" (closed ends of pipe fd pairs)
                     for (int i = 0; i < 3; i++)
                         iss.add(new FileInputStream(BIG_FILE));
-                    do {} while (count(procFDsInUse()) == procFDs.length);
+                    do {
+                        if (Thread.interrupted())
+                            return;
+                    } while (count(procFDsInUse()) == procFDs.length);
                     // hopefully this will racily occupy empty fd slot
                     iss.add(new FileInputStream(BIG_FILE));
                     Thread.sleep(1); // Widen race window
@@ -120,11 +152,15 @@
 
     static class ExecLoop implements Runnable {
         public void run() {
+            threadsStarted.countDown();
             ProcessBuilder builder = new ProcessBuilder("/bin/true");
             while (!Thread.interrupted()) {
                 try {
                     // wait for OpenLoop to finish
-                    do {} while (count(procFDsInUse()) > 0);
+                    do {
+                        if (Thread.interrupted())
+                            return;
+                    } while (count(procFDsInUse()) > 0);
                     Process process = builder.start();
                     InputStream is = process.getInputStream();
                     process.waitFor();