8034262: Test java/lang/ProcessBuilder/CloseRace.java fails
Reviewed-by: martin, dholmes
--- 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();