示例#1
0
  /** A test for scale; launch a large number (14) of subprocesses. */
  @Test
  public static void test5() {
    ConcurrentHashMap<ProcessHandle, ProcessHandle> processes = new ConcurrentHashMap<>();

    int factor = 2;
    JavaChild p1 = null;
    Instant start = Instant.now();
    try {
      p1 = JavaChild.spawnJavaChild("stdin");
      ProcessHandle p1Handle = p1.toHandle();

      printf("Spawning %d x %d x %d processes, pid: %d%n", factor, factor, factor, p1.getPid());

      // Start the first tier of subprocesses
      p1.sendAction("spawn", factor, "stdin");

      // Start the second tier of subprocesses
      p1.sendAction("child", "spawn", factor, "stdin");

      // Start the third tier of subprocesses
      p1.sendAction("child", "child", "spawn", factor, "stdin");

      int newChildren = factor * (1 + factor * (1 + factor));
      CountDownLatch spawnCount = new CountDownLatch(newChildren);

      // Gather the PIDs from the output of the spawning process
      p1.forEachOutputLine(
          (s) -> {
            String[] split = s.trim().split(" ");
            if (split.length == 3 && split[1].equals("spawn")) {
              Long child = Long.valueOf(split[2]);
              Long parent = Long.valueOf(split[0].split(":")[0]);
              processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get());
              spawnCount.countDown();
            }
          });

      // Wait for all the subprocesses to be listed as started
      Assert.assertTrue(
          spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
          "Timeout waiting for processes to start");

      // Debugging; list descendants that are not expected in processes
      List<ProcessHandle> descendants = ProcessUtil.getDescendants(p1Handle);
      long count = descendants.stream().filter(ph -> !processes.containsKey(ph)).count();
      if (count > 0) {
        descendants
            .stream()
            .filter(ph -> !processes.containsKey(ph))
            .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: "));
        ProcessUtil.logTaskList();
        Assert.assertEquals(0, count, "Extra processes in descendants");
      }

      Assert.assertEquals(getChildren(p1Handle).size(), factor, "expected direct children");
      count = getDescendants(p1Handle).size();
      long totalChildren = factor * factor * factor + factor * factor + factor;
      Assert.assertTrue(
          count >= totalChildren, "expected at least " + totalChildren + ", actual: " + count);

      List<ProcessHandle> subprocesses = getDescendants(p1Handle);
      printf(
          " descendants:  %s%n",
          subprocesses.stream().map(p -> p.getPid()).collect(Collectors.toList()));

      p1.getOutputStream().close(); // Close stdin for the controlling p1
      p1.waitFor();
    } catch (InterruptedException | IOException ex) {
      Assert.fail("Unexpected Exception", ex);
    } finally {
      printf("Duration: %s%n", Duration.between(start, Instant.now()));
      if (p1 != null) {
        p1.destroyForcibly();
      }
      processes.forEach(
          (p, parent) -> {
            if (p.isAlive()) {
              ProcessUtil.printProcess(p, "Process Cleanup: ");
              p.destroyForcibly();
            }
          });
    }
  }
示例#2
0
  /**
   * Test destroy of processes. A JavaChild is started and it starts three children. Each one is
   * then checked to be alive and listed by descendants and forcibly destroyed. After they exit they
   * should no longer be listed by descendants.
   */
  @Test
  public static void test3() {
    ConcurrentHashMap<ProcessHandle, ProcessHandle> processes = new ConcurrentHashMap<>();

    try {
      ProcessHandle self = ProcessHandle.current();

      JavaChild p1 = JavaChild.spawnJavaChild("stdin");
      ProcessHandle p1Handle = p1.toHandle();
      printf(" p1: %s%n", p1.getPid());

      int newChildren = 3;
      CountDownLatch spawnCount = new CountDownLatch(newChildren);
      // Spawn children and have them wait
      p1.sendAction("spawn", newChildren, "stdin");

      // Gather the PIDs from the output of the spawning process
      p1.forEachOutputLine(
          (s) -> {
            String[] split = s.trim().split(" ");
            if (split.length == 3 && split[1].equals("spawn")) {
              Long child = Long.valueOf(split[2]);
              Long parent = Long.valueOf(split[0].split(":")[0]);
              processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get());
              spawnCount.countDown();
            }
          });

      // Wait for all the subprocesses to be listed as started
      Assert.assertTrue(
          spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
          "Timeout waiting for processes to start");

      // Debugging; list descendants that are not expected in processes
      List<ProcessHandle> descendants = ProcessUtil.getDescendants(p1Handle);
      long count = descendants.stream().filter(ph -> !processes.containsKey(ph)).count();
      if (count > 0) {
        descendants
            .stream()
            .filter(ph -> !processes.containsKey(ph))
            .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: "));
        ProcessUtil.logTaskList();
        Assert.assertEquals(0, count, "Extra processes in descendants");
      }

      // Verify that all spawned children are alive, show up in the descendants list
      // then destroy them
      processes.forEach(
          (p, parent) -> {
            Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p);
            Assert.assertTrue(
                descendants.contains(p), "Spawned child should be listed in descendants: " + p);
            p.destroyForcibly();
          });
      Assert.assertEquals(processes.size(), newChildren, "Wrong number of children");

      // Wait for each of the processes to exit
      processes.forEach(
          (p, parent) -> {
            for (long retries = Utils.adjustTimeout(100L); retries > 0; retries--) {
              if (!p.isAlive()) {
                return; // not alive, go on to the next
              }
              // Wait a bit and retry
              try {
                Thread.sleep(100L);
              } catch (InterruptedException ie) {
                // try again
              }
            }
            printf(
                "Timeout waiting for exit of pid %s, parent: %s, info: %s%n", p, parent, p.info());
            Assert.fail("Process still alive: " + p);
          });
      p1.destroyForcibly();
      p1.waitFor();

      // Verify that none of the spawned children are still listed by descendants
      List<ProcessHandle> remaining = getDescendants(self);
      Assert.assertFalse(remaining.remove(p1Handle), "Child p1 should have exited");
      remaining = remaining.stream().filter(processes::containsKey).collect(Collectors.toList());
      Assert.assertEquals(remaining.size(), 0, "Subprocess(es) should have exited: " + remaining);

    } catch (IOException ioe) {
      Assert.fail("Spawn of subprocess failed", ioe);
    } catch (InterruptedException inte) {
      Assert.fail("InterruptedException", inte);
    } finally {
      processes.forEach(
          (p, parent) -> {
            if (p.isAlive()) {
              ProcessUtil.printProcess(p);
              p.destroyForcibly();
            }
          });
    }
  }