1 /* 2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.*; 25 import java.util.concurrent.TimeUnit; 26 27 public class ProcessKillTest implements Runnable { 28 29 private Process p; 30 private static enum OS { 31 WINDOWS, LINUX, SOLARIS, MAC 32 } 33 private static OS currentOS; 34 35 public ProcessKillTest() throws Exception { 36 String osName = System.getProperty("os.name"); 37 if(osName.toLowerCase().indexOf("win") == 0) 38 currentOS = OS.WINDOWS; 39 else if(osName.toLowerCase().indexOf("lin") == 0) 40 currentOS = OS.LINUX; 41 else if(osName.contains("OS X")) 42 currentOS = OS.MAC; 43 44 ProcessBuilder bldr; 45 if (currentOS == OS.WINDOWS) 46 bldr = new ProcessBuilder("ping", "-t", "127.0.0.1"); 47 else 48 bldr = new ProcessBuilder("./ProcessTrap.sh"); 49 bldr.redirectErrorStream(true); 50 bldr.directory(new File(".")); 51 p = bldr.start(); 52 } 53 54 public Process getProc() { 55 return p; 56 } 57 58 public void killProc(boolean force) throws Exception { 59 if(force) { 60 p.destroyForcibly().waitFor(); 61 // System.out.println(p.exitValue()); 62 if ((currentOS == OS.SOLARIS && p.exitValue() != 9) || 63 ((currentOS == OS.LINUX || currentOS == OS.MAC) 64 && p.exitValue() != 137)) 65 throw new RuntimeException("Test failed: wrong exit value"); 66 } else { 67 p.destroy(); 68 } 69 } 70 71 public boolean isAlive() { 72 return p.isAlive(); 73 } 74 75 public void run() { 76 try { 77 String line; 78 BufferedReader is = 79 new BufferedReader(new InputStreamReader(p.getInputStream())); 80 while ((line = is.readLine()) != null) 81 System.err.println("ProcessTrap: " + line); 82 } catch(IOException e) { 83 if (!e.getMessage().equals("Stream closed")) { 84 throw new RuntimeException(e); 85 } 86 } 87 } 88 89 public static void runTest(ProcessKillTest test) throws Exception { 90 TimeUnit nanos = TimeUnit.NANOSECONDS; 91 92 // this tests that the script is trapping the SIGTERM properly 93 // and that it doesn't cause the process to terminate. 94 // since windows would kill the process on a destroy(false) 95 // we don't perform this test. 96 // On Mac, it appears that when we close the processes streams 97 // after a destroy() call, the process terminates with a 98 // SIGPIPE even if it was trapping the SIGTERM, so as with 99 // windows, we skip this trap test. 100 if(currentOS == OS.SOLARIS || currentOS == OS.LINUX) 101 test.killProc(false); 102 103 long start = System.nanoTime(); 104 if (!test.isAlive() || 105 test.getProc().waitFor(0, TimeUnit.MILLISECONDS)) { 106 throw new RuntimeException( 107 "Test failed: Process exited prematurely"); 108 } 109 long end = System.nanoTime(); 110 if(nanos.toMillis(end - start) > 10) 111 throw new RuntimeException( 112 "Test failed: waitFor took too long"); 113 114 start = System.nanoTime(); 115 test.getProc().waitFor(3000, TimeUnit.MILLISECONDS); 116 end = System.nanoTime(); 117 if(nanos.toMillis(end - start) < 3000) 118 throw new RuntimeException( 119 "Test failed: waitFor didn't take long enough"); 120 121 if(currentOS == OS.WINDOWS) 122 test.killProc(false); // make sure killProc(false) works on win 123 else 124 test.killProc(true); // test destroyForcibly(true); 125 test.getProc().waitFor(); 126 127 start = System.nanoTime(); 128 if (test.isAlive() || 129 !test.getProc().waitFor(0, TimeUnit.MILLISECONDS)) { 130 throw new RuntimeException( 131 "Test failed: Process hasn't been killed, please terminate " + 132 test.getProc().toString() + " manually"); 133 } 134 end = System.nanoTime(); 135 if(nanos.toMillis(end - start) > 10) 136 throw new RuntimeException( 137 "Test failed: waitFor took too long with a timeout of 0"); 138 139 140 start = System.nanoTime(); 141 test.getProc().waitFor(100, TimeUnit.MILLISECONDS); 142 end = System.nanoTime(); 143 if(nanos.toMillis(end - start) > 10) 144 throw new RuntimeException( 145 "Test failed: waitFor took too long on dead process"); 146 147 System.out.println("Test passed"); 148 } 149 150 public static void main(String args[]) throws Exception { 151 ProcessKillTest test = new ProcessKillTest(); 152 new Thread(test).start(); 153 Thread.sleep(1000); 154 runTest(test); 155 } 156 }