test/java/lang/ProcessBuilder/Basic.java
Print this page
rev 8725 : 8024854: Basic changes and files to build the class library on AIX
Contributed-by: luchsh@linux.vnet.ibm.com, spoole@linux.vnet.ibm.com, thomas.stuefe@sap.com
Reviewed-by: alanb, prr, sla, chegar, michaelm, mullan
*** 56,65 ****
--- 56,68 ----
static final String systemRoot = System.getenv("SystemRoot");
/* used for Mac OS X only */
static final String cfUserTextEncoding = System.getenv("__CF_USER_TEXT_ENCODING");
+ /* used for AIX only */
+ static final String libpath = System.getenv("LIBPATH");
+
private static String commandOutput(Reader r) throws Throwable {
StringBuilder sb = new StringBuilder();
int c;
while ((c = r.read()) > 0)
if (c != '\r')
*** 73,83 ****
check(p.getErrorStream() == p.getErrorStream());
Reader r = new InputStreamReader(p.getInputStream(),"UTF-8");
String output = commandOutput(r);
equal(p.waitFor(), 0);
equal(p.exitValue(), 0);
! return output;
}
private static String commandOutput(ProcessBuilder pb) {
try {
return commandOutput(pb.start());
--- 76,90 ----
check(p.getErrorStream() == p.getErrorStream());
Reader r = new InputStreamReader(p.getInputStream(),"UTF-8");
String output = commandOutput(r);
equal(p.waitFor(), 0);
equal(p.exitValue(), 0);
! // The debug/fastdebug versions of the VM may write some warnings to stdout
! // (i.e. "Warning: Cannot open log file: hotspot.log" if the VM is started
! // in a directory without write permissions). These warnings will confuse tests
! // which match the entire output of the child process so better filter them out.
! return output.replaceAll("Warning:.*\\n", "");
}
private static String commandOutput(ProcessBuilder pb) {
try {
return commandOutput(pb.start());
*** 582,591 ****
--- 589,604 ----
public static boolean is() { return is; }
private static final boolean is =
System.getProperty("os.name").startsWith("Windows");
}
+ static class AIX {
+ public static boolean is() { return is; }
+ private static final boolean is =
+ System.getProperty("os.name").equals("AIX");
+ }
+
static class Unix {
public static boolean is() { return is; }
private static final boolean is =
(! Windows.is() &&
new File("/bin/sh").exists() &&
*** 635,645 ****
private final static Boolean is =
(! Windows.is() && isEnglish("LANG") && isEnglish("LC_ALL"));
private static boolean isEnglish(String envvar) {
String val = getenv(envvar);
! return (val == null) || val.matches("en.*");
}
/** Returns true if we can expect English OS error strings */
static boolean is() { return is; }
}
--- 648,658 ----
private final static Boolean is =
(! Windows.is() && isEnglish("LANG") && isEnglish("LC_ALL"));
private static boolean isEnglish(String envvar) {
String val = getenv(envvar);
! return (val == null) || val.matches("en.*") || val.matches("C");
}
/** Returns true if we can expect English OS error strings */
static boolean is() { return is; }
}
*** 710,719 ****
--- 723,740 ----
= matchAndExtract(cleanedVars,
"JAVA_MAIN_CLASS_\\d+=Basic.JavaChild,");
return cleanedVars.replace(javaMainClassStr,"");
}
+ /* Only used for AIX --
+ * AIX adds the variable AIXTHREAD_GUARDPAGES=0 to the environment.
+ * Remove it from the list of env variables
+ */
+ private static String removeAixExpectedVars(String vars) {
+ return vars.replace("AIXTHREAD_GUARDPAGES=0,","");
+ }
+
private static String sortByLinesWindowsly(String text) {
String[] lines = text.split("\n");
Arrays.sort(lines, new WindowsComparator());
StringBuilder sb = new StringBuilder();
for (String line : lines)
*** 1158,1174 ****
--- 1179,1202 ----
//----------------------------------------------------------------
try {
ProcessBuilder pb = new ProcessBuilder();
pb.environment().clear();
String expected = Windows.is() ? "SystemRoot="+systemRoot+",": "";
+ expected = AIX.is() ? "LIBPATH="+libpath+",": expected;
if (Windows.is()) {
pb.environment().put("SystemRoot", systemRoot);
}
+ if (AIX.is()) {
+ pb.environment().put("LIBPATH", libpath);
+ }
String result = getenvInChild(pb);
if (MacOSX.is()) {
result = removeMacExpectedVars(result);
}
+ if (AIX.is()) {
+ result = removeAixExpectedVars(result);
+ }
equal(result, expected);
} catch (Throwable t) { unexpected(t); }
//----------------------------------------------------------------
// System.getenv() is read-only.
*** 1679,1692 ****
--- 1707,1724 ----
} else {
envp = envpOth;
}
Process p = Runtime.getRuntime().exec(cmdp, envp);
String expected = Windows.is() ? "=C:=\\,=ExitValue=3,SystemRoot="+systemRoot+"," : "=C:=\\,";
+ expected = AIX.is() ? expected + "LIBPATH="+libpath+",": expected;
String commandOutput = commandOutput(p);
if (MacOSX.is()) {
commandOutput = removeMacExpectedVars(commandOutput);
}
+ if (AIX.is()) {
+ commandOutput = removeAixExpectedVars(commandOutput);
+ }
equal(commandOutput, expected);
if (Windows.is()) {
ProcessBuilder pb = new ProcessBuilder(childArgs);
pb.environment().clear();
pb.environment().put("SystemRoot", systemRoot);
*** 1734,1745 ****
--- 1766,1782 ----
Process p = Runtime.getRuntime().exec(cmdp, envp);
String commandOutput = commandOutput(p);
if (MacOSX.is()) {
commandOutput = removeMacExpectedVars(commandOutput);
}
+ if (AIX.is()) {
+ commandOutput = removeAixExpectedVars(commandOutput);
+ }
check(commandOutput.equals(Windows.is()
? "LC_ALL=C,SystemRoot="+systemRoot+","
+ : AIX.is()
+ ? "LC_ALL=C,LIBPATH="+libpath+","
: "LC_ALL=C,"),
"Incorrect handling of envstrings containing NULs");
} catch (Throwable t) { unexpected(t); }
//----------------------------------------------------------------
*** 2013,2023 ****
//----------------------------------------------------------------
try {
if (Unix.is()
&& new File("/bin/bash").exists()
&& new File("/bin/sleep").exists()) {
! final String[] cmd = { "/bin/bash", "-c", "(/bin/sleep 6666)" };
final ProcessBuilder pb = new ProcessBuilder(cmd);
final Process p = pb.start();
final InputStream stdout = p.getInputStream();
final InputStream stderr = p.getErrorStream();
final OutputStream stdin = p.getOutputStream();
--- 2050,2065 ----
//----------------------------------------------------------------
try {
if (Unix.is()
&& new File("/bin/bash").exists()
&& new File("/bin/sleep").exists()) {
! // Notice that we only destroy the process created by us (i.e.
! // our child) but not our grandchild (i.e. '/bin/sleep'). So
! // pay attention that the grandchild doesn't run too long to
! // avoid polluting the process space with useless processes.
! // Running the grandchild for 60s should be more than enough.
! final String[] cmd = { "/bin/bash", "-c", "(/bin/sleep 60)" };
final ProcessBuilder pb = new ProcessBuilder(cmd);
final Process p = pb.start();
final InputStream stdout = p.getInputStream();
final InputStream stderr = p.getErrorStream();
final OutputStream stdin = p.getOutputStream();
*** 2035,2050 ****
catch (Throwable t) { unexpected(t); }}};
reader.setDaemon(true);
reader.start();
Thread.sleep(100);
p.destroy();
- // Subprocess is now dead, but file descriptors remain open.
check(p.waitFor() != 0);
check(p.exitValue() != 0);
stdout.close();
stderr.close();
stdin.close();
//----------------------------------------------------------
// There remain unsolved issues with asynchronous close.
// Here's a highly non-portable experiment to demonstrate:
//----------------------------------------------------------
if (Boolean.getBoolean("wakeupJeff!")) {
--- 2077,2106 ----
catch (Throwable t) { unexpected(t); }}};
reader.setDaemon(true);
reader.start();
Thread.sleep(100);
p.destroy();
check(p.waitFor() != 0);
check(p.exitValue() != 0);
+ // Subprocess is now dead, but file descriptors remain open.
+ // Make sure the test will fail if we don't manage to close
+ // the open streams within 30 seconds. Notice that this time
+ // must be shorter than the sleep time of the grandchild.
+ Timer t = new Timer("test/java/lang/ProcessBuilder/Basic.java process reaper", true);
+ t.schedule(new TimerTask() {
+ public void run() {
+ fail("Subprocesses which create subprocesses of " +
+ "their own caused the parent to hang while " +
+ "waiting for file descriptors to be closed.");
+ System.exit(-1);
+ }
+ }, 30000);
stdout.close();
stderr.close();
stdin.close();
+ // All streams successfully closed so we can cancel the timer.
+ t.cancel();
//----------------------------------------------------------
// There remain unsolved issues with asynchronous close.
// Here's a highly non-portable experiment to demonstrate:
//----------------------------------------------------------
if (Boolean.getBoolean("wakeupJeff!")) {
*** 2186,2197 ****
if (!p.isAlive() || p.waitFor(0, TimeUnit.MILLISECONDS)) {
fail("Test failed: Process exited prematurely");
}
long end = System.nanoTime();
// give waitFor(timeout) a wide berth (100ms)
! if ((end - start) > 100000000)
! fail("Test failed: waitFor took too long");
p.destroy();
p.waitFor();
if (p.isAlive() ||
--- 2242,2254 ----
if (!p.isAlive() || p.waitFor(0, TimeUnit.MILLISECONDS)) {
fail("Test failed: Process exited prematurely");
}
long end = System.nanoTime();
// give waitFor(timeout) a wide berth (100ms)
! // Old AIX machines my need a little longer.
! if ((end - start) > 100000000L * (AIX.is() ? 4 : 1))
! fail("Test failed: waitFor took too long (" + (end - start) + "ns)");
p.destroy();
p.waitFor();
if (p.isAlive() ||
*** 2214,2232 ****
p.waitFor(1000, TimeUnit.MILLISECONDS);
long end = System.nanoTime();
if ((end - start) < 500000000)
! fail("Test failed: waitFor didn't take long enough");
p.destroy();
start = System.nanoTime();
p.waitFor(1000, TimeUnit.MILLISECONDS);
end = System.nanoTime();
if ((end - start) > 900000000)
! fail("Test failed: waitFor took too long on a dead process.");
} catch (Throwable t) { unexpected(t); }
//----------------------------------------------------------------
// Check that Process.waitFor(timeout, TimeUnit.MILLISECONDS)
// interrupt works as expected.
--- 2271,2289 ----
p.waitFor(1000, TimeUnit.MILLISECONDS);
long end = System.nanoTime();
if ((end - start) < 500000000)
! fail("Test failed: waitFor didn't take long enough (" + (end - start) + "ns)");
p.destroy();
start = System.nanoTime();
p.waitFor(1000, TimeUnit.MILLISECONDS);
end = System.nanoTime();
if ((end - start) > 900000000)
! fail("Test failed: waitFor took too long on a dead process. (" + (end - start) + "ns)");
} catch (Throwable t) { unexpected(t); }
//----------------------------------------------------------------
// Check that Process.waitFor(timeout, TimeUnit.MILLISECONDS)
// interrupt works as expected.