diff --git a/test/java/lang/ProcessBuilder/CloseRace.java b/test/java/lang/ProcessBuilder/CloseRace.java index ff2e81fe7a8b6664ea44a69b06e5641ed36d4419..a9afbd2ba915ba28f4d7356dd037bbec65483a03 100644 --- a/test/java/lang/ProcessBuilder/CloseRace.java +++ b/test/java/lang/ProcessBuilder/CloseRace.java @@ -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 @@ public class CloseRace { 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 @@ public class CloseRace { return count; } + static void dumpAllStacks() { + System.err.println("Start of dump"); + final Map 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 @@ public class CloseRace { 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 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 @@ public class CloseRace { 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();