# HG changeset patch # User rriggs # Date 1436318705 14400 # Node ID c1e1214cebd3720d58cb77a6889ebd510a35dc34 # Parent 965b2f38342e21e172af10d6cb37d1e5a6bc1080 8085981: java/lang/ProcessHandle/OnExitTest.java: AssertionError: Child onExit not called Summary: a race condition caused an erroneous fault Reviewed-by: darcy diff -r 965b2f38342e -r c1e1214cebd3 jdk/test/java/lang/ProcessHandle/OnExitTest.java --- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java Tue Jul 07 16:54:52 2015 -0400 +++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java Tue Jul 07 21:25:05 2015 -0400 @@ -123,16 +123,17 @@ children = getAllChildren(procHandle); - ArrayBlockingQueue completions = new ArrayBlockingQueue<>(expected + 1); + ConcurrentHashMap> completions = + new ConcurrentHashMap<>(); Instant startTime = Instant.now(); // Create a future for each of the 9 children processes.forEach( (p, parent) -> { - p.onExit().whenComplete((ph, ex) -> { + CompletableFuture cf = p.onExit().whenComplete((ph, ex) -> { Duration elapsed = Duration.between(startTime, Instant.now()); - completions.add(ph); printf("whenComplete: pid: %s, exception: %s, thread: %s, elapsed: %s%n", ph, ex, Thread.currentThread(), elapsed); }); + completions.put(p, cf); }); // Check that each of the spawned processes is included in the children @@ -153,20 +154,23 @@ proc.destroy(); // kill off the parent proc.waitFor(); - // Wait for all the processes to be completed + // Wait for all the processes and corresponding onExit CF to be completed processes.forEach((p, parent) -> { try { p.onExit().get(); + completions.get(p).join(); } catch (InterruptedException | ExecutionException ex) { // ignore } }); - // Verify that all 9 exit handlers were called - processes.forEach((p, parent) -> - Assert.assertTrue(completions.contains(p), "Child onExit not called: " + p - + ", parent: " + parent - + ": " + p.info())); + // Verify that all 9 exit handlers were called with the correct ProcessHandle + processes.forEach((p, parent) -> { + ProcessHandle value = completions.get(p).getNow(null); + Assert.assertEquals(p, value, "onExit.get value expected: " + p + + ", actual: " + value + + ": " + p.info()); + }); // Show the status of the original children children.forEach(p -> printProcess(p, "after onExit:"));