1 import java.util.Map; 2 3 public class Main { main(String[] args)4 static public void main(String[] args) throws Exception { 5 checkManager(); 6 7 // Warm up the reaper so that there are no issues with scheduling because of static 8 // initialization. 9 { 10 ProcessBuilder pb = new ProcessBuilder("sleep", "0"); 11 Process proc = pb.start(); 12 proc.waitFor(); 13 waitForReaperTimedWaiting(true /* reaperMustExist */); 14 } 15 16 for (int i = 1; i <= 2; i++) { 17 System.out.println("\nspawning child #" + i); 18 child(); 19 Thread.sleep(2000); 20 checkManager(); 21 } 22 System.out.println("\ndone!"); 23 } 24 child()25 static private void child() throws Exception { 26 System.out.println("spawning child"); 27 ProcessBuilder pb = new ProcessBuilder("sleep", "5"); 28 Process proc = pb.start(); 29 Thread.sleep(250); 30 checkManager(); 31 proc.waitFor(); 32 System.out.println("child died"); 33 } 34 isReaperThread(Thread t)35 private static boolean isReaperThread(Thread t) { 36 String name = t.getName(); 37 return name.indexOf("process reaper") >= 0; 38 } 39 checkManager()40 static private void checkManager() { 41 Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces(); 42 boolean found = false; 43 44 for (Map.Entry<Thread, StackTraceElement[]> entry : 45 traces.entrySet()) { 46 Thread t = entry.getKey(); 47 if (isReaperThread(t)) { 48 Thread.State state = t.getState(); 49 System.out.println("process manager: " + state); 50 if (state != Thread.State.RUNNABLE && state != Thread.State.TIMED_WAITING) { 51 for (StackTraceElement e : entry.getValue()) { 52 System.out.println(" " + e); 53 } 54 } 55 found = true; 56 } 57 } 58 59 if (! found) { 60 System.out.println("process manager: nonexistent"); 61 } 62 } 63 waitForReaperTimedWaiting(boolean reaperMustExist)64 private static void waitForReaperTimedWaiting(boolean reaperMustExist) { 65 for (;;) { 66 Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces(); 67 68 boolean ok = true; 69 boolean found = false; 70 71 for (Thread t : traces.keySet()) { 72 if (isReaperThread(t)) { 73 found = true; 74 Thread.State state = t.getState(); 75 if (state != Thread.State.TIMED_WAITING) { 76 ok = false; 77 break; 78 } 79 } 80 } 81 82 if (ok && (!reaperMustExist || found)) { 83 return; 84 } 85 86 try { 87 Thread.sleep(100); 88 } catch (Exception e) { 89 // Ignore. 90 } 91 } 92 } 93 } 94