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.