2000 while (unsafe.tryMonitorEnter(s)) { 2001 unsafe.monitorExit(s); 2002 Thread.sleep(1); 2003 } 2004 } 2005 p.destroy(); 2006 thread.join(); 2007 } 2008 } catch (Throwable t) { unexpected(t); } 2009 2010 //---------------------------------------------------------------- 2011 // Check that subprocesses which create subprocesses of their 2012 // own do not cause parent to hang waiting for file 2013 // descriptors to be closed. 2014 //---------------------------------------------------------------- 2015 try { 2016 if (Unix.is() 2017 && new File("/bin/bash").exists() 2018 && new File("/bin/sleep").exists()) { 2019 final String[] cmd = { "/bin/bash", "-c", "(/bin/sleep 6666)" }; 2020 final String[] cmdkill = { "/bin/bash", "-c", "(/usr/bin/pkill -f \"sleep 6666\")" }; 2021 final ProcessBuilder pb = new ProcessBuilder(cmd); 2022 final Process p = pb.start(); 2023 final InputStream stdout = p.getInputStream(); 2024 final InputStream stderr = p.getErrorStream(); 2025 final OutputStream stdin = p.getOutputStream(); 2026 final Thread reader = new Thread() { 2027 public void run() { 2028 try { stdout.read(); } 2029 catch (IOException e) { 2030 // Check that reader failed because stream was 2031 // asynchronously closed. 2032 // e.printStackTrace(); 2033 if (EnglishUnix.is() && 2034 ! (e.getMessage().matches(".*Bad file.*"))) 2035 unexpected(e); 2036 } 2037 catch (Throwable t) { unexpected(t); }}}; 2038 reader.setDaemon(true); 2039 reader.start(); 2040 Thread.sleep(100); 2041 p.destroy(); 2042 // Subprocess is now dead, but file descriptors remain open. 2043 check(p.waitFor() != 0); 2044 check(p.exitValue() != 0); 2045 stdout.close(); 2046 stderr.close(); 2047 stdin.close(); 2048 new ProcessBuilder(cmdkill).start(); 2049 //---------------------------------------------------------- 2050 // There remain unsolved issues with asynchronous close. 2051 // Here's a highly non-portable experiment to demonstrate: 2052 //---------------------------------------------------------- 2053 if (Boolean.getBoolean("wakeupJeff!")) { 2054 System.out.println("wakeupJeff!"); 2055 // Initialize signal handler for INTERRUPT_SIGNAL. 2056 new FileInputStream("/bin/sleep").getChannel().close(); 2057 // Send INTERRUPT_SIGNAL to every thread in this java. 2058 String[] wakeupJeff = { 2059 "/bin/bash", "-c", 2060 "/bin/ps --noheaders -Lfp $PPID | " + 2061 "/usr/bin/perl -nale 'print $F[3]' | " + 2062 // INTERRUPT_SIGNAL == 62 on my machine du jour. 2063 "/usr/bin/xargs kill -62" 2064 }; 2065 new ProcessBuilder(wakeupJeff).start().waitFor(); 2066 // If wakeupJeff worked, reader probably got EBADF. 2067 reader.join(); 2068 } 2069 } 2070 } catch (Throwable t) { unexpected(t); } 2071 2072 //---------------------------------------------------------------- 2073 // Attempt to start process with insufficient permissions fails. 2074 //---------------------------------------------------------------- 2075 try { 2076 new File("emptyCommand").delete(); 2077 new FileOutputStream("emptyCommand").close(); 2078 new File("emptyCommand").setExecutable(false); 2079 new ProcessBuilder("./emptyCommand").start(); 2080 fail("Expected IOException not thrown"); 2081 } catch (IOException e) { 2082 new File("./emptyCommand").delete(); 2083 String m = e.getMessage(); 2084 if (EnglishUnix.is() && 2085 ! matches(m, "Permission denied")) 2086 unexpected(e); 2087 } catch (Throwable t) { unexpected(t); } 2088 | 2000 while (unsafe.tryMonitorEnter(s)) { 2001 unsafe.monitorExit(s); 2002 Thread.sleep(1); 2003 } 2004 } 2005 p.destroy(); 2006 thread.join(); 2007 } 2008 } catch (Throwable t) { unexpected(t); } 2009 2010 //---------------------------------------------------------------- 2011 // Check that subprocesses which create subprocesses of their 2012 // own do not cause parent to hang waiting for file 2013 // descriptors to be closed. 2014 //---------------------------------------------------------------- 2015 try { 2016 if (Unix.is() 2017 && new File("/bin/bash").exists() 2018 && new File("/bin/sleep").exists()) { 2019 final String[] cmd = { "/bin/bash", "-c", "(/bin/sleep 6666)" }; 2020 final ProcessBuilder pb = new ProcessBuilder(cmd); 2021 final Process p = pb.start(); 2022 final InputStream stdout = p.getInputStream(); 2023 final InputStream stderr = p.getErrorStream(); 2024 final OutputStream stdin = p.getOutputStream(); 2025 final Thread reader = new Thread() { 2026 public void run() { 2027 try { stdout.read(); } 2028 catch (IOException e) { 2029 // Check that reader failed because stream was 2030 // asynchronously closed. 2031 // e.printStackTrace(); 2032 if (EnglishUnix.is() && 2033 ! (e.getMessage().matches(".*Bad file.*"))) 2034 unexpected(e); 2035 } 2036 catch (Throwable t) { unexpected(t); }}}; 2037 reader.setDaemon(true); 2038 reader.start(); 2039 Thread.sleep(100); 2040 p.destroy(); 2041 // Subprocess is now dead, but file descriptors remain open. 2042 check(p.waitFor() != 0); 2043 check(p.exitValue() != 0); 2044 stdout.close(); 2045 stderr.close(); 2046 stdin.close(); 2047 //---------------------------------------------------------- 2048 // There remain unsolved issues with asynchronous close. 2049 // Here's a highly non-portable experiment to demonstrate: 2050 //---------------------------------------------------------- 2051 if (Boolean.getBoolean("wakeupJeff!")) { 2052 System.out.println("wakeupJeff!"); 2053 long startTime = System.nanoTime(); 2054 // Initialize signal handler for INTERRUPT_SIGNAL. 2055 new FileInputStream("/bin/sleep").getChannel().close(); 2056 // Send INTERRUPT_SIGNAL to every thread in this java. 2057 String[] wakeupJeff = { 2058 "/bin/bash", "-c", 2059 "/bin/ps --noheaders -Lfp $PPID | " + 2060 "/usr/bin/perl -nale 'print $F[3]' | " + 2061 // INTERRUPT_SIGNAL == 62 on my machine du jour. 2062 "/usr/bin/xargs kill -62" 2063 }; 2064 new ProcessBuilder(wakeupJeff).start().waitFor(); 2065 // If wakeupJeff worked, reader probably got EBADF. 2066 long timeout = 60L * 1000L; 2067 reader.join(timeout); 2068 long elapsedTimeMillis = 2069 (System.nanoTime() - startTime) / (1024L * 1024L); 2070 check(elapsedTimeMillis < timeout); 2071 check(!reader.isAlive()); 2072 } 2073 // Try to clean up the sleep process, but don't fret about it. 2074 try { 2075 new ProcessBuilder("/usr/bin/pkill", "-f", "sleep 6666").start(); 2076 } catch (IOException noPkillCommandInstalled) { } 2077 } 2078 } catch (Throwable t) { unexpected(t); } 2079 2080 //---------------------------------------------------------------- 2081 // Attempt to start process with insufficient permissions fails. 2082 //---------------------------------------------------------------- 2083 try { 2084 new File("emptyCommand").delete(); 2085 new FileOutputStream("emptyCommand").close(); 2086 new File("emptyCommand").setExecutable(false); 2087 new ProcessBuilder("./emptyCommand").start(); 2088 fail("Expected IOException not thrown"); 2089 } catch (IOException e) { 2090 new File("./emptyCommand").delete(); 2091 String m = e.getMessage(); 2092 if (EnglishUnix.is() && 2093 ! matches(m, "Permission denied")) 2094 unexpected(e); 2095 } catch (Throwable t) { unexpected(t); } 2096 |