mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
8034262: Test java/lang/ProcessBuilder/CloseRace.java fails
Reviewed-by: martin, dholmes
This commit is contained in:
parent
323843f397
commit
d3271335ad
1 changed files with 41 additions and 5 deletions
|
@ -33,6 +33,8 @@
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
public class CloseRace {
|
public class CloseRace {
|
||||||
private static final String BIG_FILE = "bigfile";
|
private static final String BIG_FILE = "bigfile";
|
||||||
|
@ -43,6 +45,9 @@ public class CloseRace {
|
||||||
private static final int testDurationSeconds
|
private static final int testDurationSeconds
|
||||||
= Integer.getInteger("test.duration", 600);
|
= Integer.getInteger("test.duration", 600);
|
||||||
|
|
||||||
|
private static final CountDownLatch threadsStarted
|
||||||
|
= new CountDownLatch(2);
|
||||||
|
|
||||||
static boolean fdInUse(int i) {
|
static boolean fdInUse(int i) {
|
||||||
return new File("/proc/self/fd/" + i).exists();
|
return new File("/proc/self/fd/" + i).exists();
|
||||||
}
|
}
|
||||||
|
@ -61,6 +66,18 @@ public class CloseRace {
|
||||||
return count;
|
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 {
|
public static void main(String args[]) throws Exception {
|
||||||
if (!(new File("/proc/self/fd").isDirectory()))
|
if (!(new File("/proc/self/fd").isDirectory()))
|
||||||
return;
|
return;
|
||||||
|
@ -84,26 +101,41 @@ public class CloseRace {
|
||||||
for (Thread thread : threads)
|
for (Thread thread : threads)
|
||||||
thread.start();
|
thread.start();
|
||||||
|
|
||||||
|
threadsStarted.await();
|
||||||
Thread.sleep(testDurationSeconds * 1000);
|
Thread.sleep(testDurationSeconds * 1000);
|
||||||
|
|
||||||
for (Thread thread : threads)
|
for (Thread thread : threads)
|
||||||
thread.interrupt();
|
thread.interrupt();
|
||||||
for (Thread thread : threads)
|
for (Thread thread : threads) {
|
||||||
thread.join();
|
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 {
|
static class OpenLoop implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
threadsStarted.countDown();
|
||||||
while (!Thread.interrupted()) {
|
while (!Thread.interrupted()) {
|
||||||
try {
|
try {
|
||||||
// wait for ExecLoop to finish creating process
|
// 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);
|
List<InputStream> iss = new ArrayList<>(4);
|
||||||
|
|
||||||
// eat up three "holes" (closed ends of pipe fd pairs)
|
// eat up three "holes" (closed ends of pipe fd pairs)
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
iss.add(new FileInputStream(BIG_FILE));
|
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
|
// hopefully this will racily occupy empty fd slot
|
||||||
iss.add(new FileInputStream(BIG_FILE));
|
iss.add(new FileInputStream(BIG_FILE));
|
||||||
Thread.sleep(1); // Widen race window
|
Thread.sleep(1); // Widen race window
|
||||||
|
@ -120,11 +152,15 @@ public class CloseRace {
|
||||||
|
|
||||||
static class ExecLoop implements Runnable {
|
static class ExecLoop implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
threadsStarted.countDown();
|
||||||
ProcessBuilder builder = new ProcessBuilder("/bin/true");
|
ProcessBuilder builder = new ProcessBuilder("/bin/true");
|
||||||
while (!Thread.interrupted()) {
|
while (!Thread.interrupted()) {
|
||||||
try {
|
try {
|
||||||
// wait for OpenLoop to finish
|
// wait for OpenLoop to finish
|
||||||
do {} while (count(procFDsInUse()) > 0);
|
do {
|
||||||
|
if (Thread.interrupted())
|
||||||
|
return;
|
||||||
|
} while (count(procFDsInUse()) > 0);
|
||||||
Process process = builder.start();
|
Process process = builder.start();
|
||||||
InputStream is = process.getInputStream();
|
InputStream is = process.getInputStream();
|
||||||
process.waitFor();
|
process.waitFor();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue