コード例 #1
0
 /**
  * Is any of the subprocesses in the process-tree alive? Used only in tests.
  *
  * @return true if any of the processes in the process-tree is alive, false otherwise.
  */
 private static boolean isAnyProcessInTreeAlive(ProcfsBasedProcessTree processTree) {
   for (String pId : processTree.getCurrentProcessIDs()) {
     if (isAlive(pId)) {
       return true;
     }
   }
   return false;
 }
コード例 #2
0
  /**
   * Verifies ProcfsBasedProcessTree.checkPidPgrpidForMatch() in case of 'constructProcessInfo()
   * returning null' by not writing stat file for the mock process
   *
   * @throws IOException if there was a problem setting up the fake procfs directories or files.
   */
  @Test
  public void testDestroyProcessTree() throws IOException {
    // test process
    String pid = "100";
    // create the fake procfs root directory.
    File procfsRootDir = new File(TEST_ROOT_DIR, "proc");

    try {
      setupProcfsRootDir(procfsRootDir);

      // crank up the process tree class.
      createProcessTree(pid, procfsRootDir.getAbsolutePath());

      // Let us not create stat file for pid 100.
      Assert.assertTrue(
          ProcfsBasedProcessTree.checkPidPgrpidForMatch(pid, procfsRootDir.getAbsolutePath()));
    } finally {
      FileUtil.fullyDelete(procfsRootDir);
    }
  }
コード例 #3
0
  @Test
  public void testProcessTree() throws Exception {

    try {
      if (!ProcfsBasedProcessTree.isAvailable()) {
        System.out.println("ProcfsBasedProcessTree is not available on this system. Not testing");
        return;
      }
    } catch (Exception e) {
      LOG.info(StringUtils.stringifyException(e));
      return;
    }
    // create shell script
    Random rm = new Random();
    File tempFile =
        new File(TEST_ROOT_DIR, getClass().getName() + "_shellScript_" + rm.nextInt() + ".sh");
    tempFile.deleteOnExit();
    shellScript = TEST_ROOT_DIR + File.separator + tempFile.getName();

    // create pid file
    tempFile = new File(TEST_ROOT_DIR, getClass().getName() + "_pidFile_" + rm.nextInt() + ".pid");
    tempFile.deleteOnExit();
    pidFile = TEST_ROOT_DIR + File.separator + tempFile.getName();

    lowestDescendant = TEST_ROOT_DIR + File.separator + "lowestDescendantPidFile";

    // write to shell-script
    try {
      FileWriter fWriter = new FileWriter(shellScript);
      fWriter.write(
          "# rogue task\n"
              + "sleep 1\n"
              + "echo hello\n"
              + "if [ $1 -ne 0 ]\n"
              + "then\n"
              + " sh "
              + shellScript
              + " $(($1-1))\n"
              + "else\n"
              + " echo $$ > "
              + lowestDescendant
              + "\n"
              + " while true\n do\n"
              + "  sleep 5\n"
              + " done\n"
              + "fi");
      fWriter.close();
    } catch (IOException ioe) {
      LOG.info("Error: " + ioe);
      return;
    }

    Thread t = new RogueTaskThread();
    t.start();
    String pid = getRogueTaskPID();
    LOG.info("Root process pid: " + pid);
    ProcfsBasedProcessTree p = createProcessTree(pid);
    p.getProcessTree(); // initialize
    LOG.info("ProcessTree: " + p.toString());

    File leaf = new File(lowestDescendant);
    // wait till lowest descendant process of Rougue Task starts execution
    while (!leaf.exists()) {
      try {
        Thread.sleep(500);
      } catch (InterruptedException ie) {
        break;
      }
    }

    p.getProcessTree(); // reconstruct
    LOG.info("ProcessTree: " + p.toString());

    // Get the process-tree dump
    String processTreeDump = p.getProcessTreeDump();

    // destroy the process and all its subprocesses
    destroyProcessTree(pid);

    if (isSetsidAvailable()) { // whole processtree should be gone
      Assert.assertFalse("Proceesses in process group live", isAnyProcessInTreeAlive(p));
    } else { // process should be gone
      Assert.assertFalse("ProcessTree must have been gone", isAlive(pid));
    }

    LOG.info("Process-tree dump follows: \n" + processTreeDump);
    Assert.assertTrue(
        "Process-tree dump doesn't start with a proper header",
        processTreeDump.startsWith(
            "\t|- PID PPID PGRPID SESSID CMD_NAME "
                + "USER_MODE_TIME(MILLIS) SYSTEM_TIME(MILLIS) VMEM_USAGE(BYTES) "
                + "RSSMEM_USAGE(PAGES) FULL_CMD_LINE\n"));
    for (int i = N; i >= 0; i--) {
      String cmdLineDump =
          "\\|- [0-9]+ [0-9]+ [0-9]+ [0-9]+ \\(sh\\)"
              + " [0-9]+ [0-9]+ [0-9]+ [0-9]+ sh "
              + shellScript
              + " "
              + i;
      Pattern pat = Pattern.compile(cmdLineDump);
      Matcher mat = pat.matcher(processTreeDump);
      Assert.assertTrue(
          "Process-tree dump doesn't contain the cmdLineDump of " + i + "th process!", mat.find());
    }

    // Not able to join thread sometimes when forking with large N.
    try {
      t.join(2000);
      LOG.info("RogueTaskThread successfully joined.");
    } catch (InterruptedException ie) {
      LOG.info("Interrupted while joining RogueTaskThread.");
    }

    // ProcessTree is gone now. Any further calls should be sane.
    p.getProcessTree();
    Assert.assertFalse("ProcessTree must have been gone", isAlive(pid));
    Assert.assertTrue(
        "Cumulative vmem for the gone-process is "
            + p.getCumulativeVmem()
            + " . It should be zero.",
        p.getCumulativeVmem() == 0);
    Assert.assertTrue(p.toString().equals("[ ]"));
  }
コード例 #4
0
  /**
   * Test the correctness of process-tree dump.
   *
   * @throws IOException
   */
  @Test
  public void testProcessTreeDump() throws IOException {

    String[] pids = {"100", "200", "300", "400", "500", "600"};

    File procfsRootDir = new File(TEST_ROOT_DIR, "proc");

    try {
      setupProcfsRootDir(procfsRootDir);
      setupPidDirs(procfsRootDir, pids);

      int numProcesses = pids.length;
      // Processes 200, 300, 400 and 500 are descendants of 100. 600 is not.
      ProcessStatInfo[] procInfos = new ProcessStatInfo[numProcesses];
      procInfos[0] =
          new ProcessStatInfo(
              new String[] {"100", "proc1", "1", "100", "100", "100000", "100", "1000", "200"});
      procInfos[1] =
          new ProcessStatInfo(
              new String[] {"200", "proc2", "100", "100", "100", "200000", "200", "2000", "400"});
      procInfos[2] =
          new ProcessStatInfo(
              new String[] {"300", "proc3", "200", "100", "100", "300000", "300", "3000", "600"});
      procInfos[3] =
          new ProcessStatInfo(
              new String[] {"400", "proc4", "200", "100", "100", "400000", "400", "4000", "800"});
      procInfos[4] =
          new ProcessStatInfo(
              new String[] {"500", "proc5", "400", "100", "100", "400000", "400", "4000", "800"});
      procInfos[5] =
          new ProcessStatInfo(
              new String[] {"600", "proc6", "1", "1", "1", "400000", "400", "4000", "800"});

      String[] cmdLines = new String[numProcesses];
      cmdLines[0] = "proc1 arg1 arg2";
      cmdLines[1] = "proc2 arg3 arg4";
      cmdLines[2] = "proc3 arg5 arg6";
      cmdLines[3] = "proc4 arg7 arg8";
      cmdLines[4] = "proc5 arg9 arg10";
      cmdLines[5] = "proc6 arg11 arg12";

      writeStatFiles(procfsRootDir, pids, procInfos);
      writeCmdLineFiles(procfsRootDir, pids, cmdLines);

      ProcfsBasedProcessTree processTree =
          createProcessTree("100", procfsRootDir.getAbsolutePath());
      // build the process tree.
      processTree.getProcessTree();

      // Get the process-tree dump
      String processTreeDump = processTree.getProcessTreeDump();

      LOG.info("Process-tree dump follows: \n" + processTreeDump);
      Assert.assertTrue(
          "Process-tree dump doesn't start with a proper header",
          processTreeDump.startsWith(
              "\t|- PID PPID PGRPID SESSID CMD_NAME "
                  + "USER_MODE_TIME(MILLIS) SYSTEM_TIME(MILLIS) VMEM_USAGE(BYTES) "
                  + "RSSMEM_USAGE(PAGES) FULL_CMD_LINE\n"));
      for (int i = 0; i < 5; i++) {
        ProcessStatInfo p = procInfos[i];
        Assert.assertTrue(
            "Process-tree dump doesn't contain the cmdLineDump of process " + p.pid,
            processTreeDump.contains(
                "\t|- "
                    + p.pid
                    + " "
                    + p.ppid
                    + " "
                    + p.pgrpId
                    + " "
                    + p.session
                    + " ("
                    + p.name
                    + ") "
                    + p.utime
                    + " "
                    + p.stime
                    + " "
                    + p.vmem
                    + " "
                    + p.rssmemPage
                    + " "
                    + cmdLines[i]));
      }

      // 600 should not be in the dump
      ProcessStatInfo p = procInfos[5];
      Assert.assertFalse(
          "Process-tree dump shouldn't contain the cmdLineDump of process " + p.pid,
          processTreeDump.contains(
              "\t|- "
                  + p.pid
                  + " "
                  + p.ppid
                  + " "
                  + p.pgrpId
                  + " "
                  + p.session
                  + " ("
                  + p.name
                  + ") "
                  + p.utime
                  + " "
                  + p.stime
                  + " "
                  + p.vmem
                  + " "
                  + cmdLines[5]));
    } finally {
      FileUtil.fullyDelete(procfsRootDir);
    }
  }
コード例 #5
0
  /**
   * Tests that cumulative memory is computed only for processes older than a given age.
   *
   * @throws IOException if there was a problem setting up the fake procfs directories or files.
   */
  @Test
  public void testMemForOlderProcesses() throws IOException {
    // initial list of processes
    String[] pids = {"100", "200", "300", "400"};
    // create the fake procfs root directory.
    File procfsRootDir = new File(TEST_ROOT_DIR, "proc");

    try {
      setupProcfsRootDir(procfsRootDir);
      setupPidDirs(procfsRootDir, pids);

      // create stat objects.
      // assuming 100, 200 and 400 are in tree, 300 is not.
      ProcessStatInfo[] procInfos = new ProcessStatInfo[4];
      procInfos[0] =
          new ProcessStatInfo(new String[] {"100", "proc1", "1", "100", "100", "100000", "100"});
      procInfos[1] =
          new ProcessStatInfo(new String[] {"200", "proc2", "100", "100", "100", "200000", "200"});
      procInfos[2] =
          new ProcessStatInfo(new String[] {"300", "proc3", "1", "300", "300", "300000", "300"});
      procInfos[3] =
          new ProcessStatInfo(new String[] {"400", "proc4", "100", "100", "100", "400000", "400"});

      writeStatFiles(procfsRootDir, pids, procInfos);

      // crank up the process tree class.
      ProcfsBasedProcessTree processTree =
          createProcessTree("100", procfsRootDir.getAbsolutePath());
      // build the process tree.
      processTree.getProcessTree();

      // verify cumulative memory
      Assert.assertEquals(
          "Cumulative memory does not match", 700000L, processTree.getCumulativeVmem());

      // write one more process as child of 100.
      String[] newPids = {"500"};
      setupPidDirs(procfsRootDir, newPids);

      ProcessStatInfo[] newProcInfos = new ProcessStatInfo[1];
      newProcInfos[0] =
          new ProcessStatInfo(new String[] {"500", "proc5", "100", "100", "100", "500000", "500"});
      writeStatFiles(procfsRootDir, newPids, newProcInfos);

      // check memory includes the new process.
      processTree.getProcessTree();
      Assert.assertEquals(
          "Cumulative vmem does not include new process",
          1200000L,
          processTree.getCumulativeVmem());
      long cumuRssMem =
          ProcfsBasedProcessTree.PAGE_SIZE > 0 ? 1200L * ProcfsBasedProcessTree.PAGE_SIZE : 0L;
      Assert.assertEquals(
          "Cumulative rssmem does not include new process",
          cumuRssMem,
          processTree.getCumulativeRssmem());

      // however processes older than 1 iteration will retain the older value
      Assert.assertEquals(
          "Cumulative vmem shouldn't have included new process",
          700000L,
          processTree.getCumulativeVmem(1));
      cumuRssMem =
          ProcfsBasedProcessTree.PAGE_SIZE > 0 ? 700L * ProcfsBasedProcessTree.PAGE_SIZE : 0L;
      Assert.assertEquals(
          "Cumulative rssmem shouldn't have included new process",
          cumuRssMem,
          processTree.getCumulativeRssmem(1));

      // one more process
      newPids = new String[] {"600"};
      setupPidDirs(procfsRootDir, newPids);

      newProcInfos = new ProcessStatInfo[1];
      newProcInfos[0] =
          new ProcessStatInfo(new String[] {"600", "proc6", "100", "100", "100", "600000", "600"});
      writeStatFiles(procfsRootDir, newPids, newProcInfos);

      // refresh process tree
      processTree.getProcessTree();

      // processes older than 2 iterations should be same as before.
      Assert.assertEquals(
          "Cumulative vmem shouldn't have included new processes",
          700000L,
          processTree.getCumulativeVmem(2));
      cumuRssMem =
          ProcfsBasedProcessTree.PAGE_SIZE > 0 ? 700L * ProcfsBasedProcessTree.PAGE_SIZE : 0L;
      Assert.assertEquals(
          "Cumulative rssmem shouldn't have included new processes",
          cumuRssMem,
          processTree.getCumulativeRssmem(2));

      // processes older than 1 iteration should not include new process,
      // but include process 500
      Assert.assertEquals(
          "Cumulative vmem shouldn't have included new processes",
          1200000L,
          processTree.getCumulativeVmem(1));
      cumuRssMem =
          ProcfsBasedProcessTree.PAGE_SIZE > 0 ? 1200L * ProcfsBasedProcessTree.PAGE_SIZE : 0L;
      Assert.assertEquals(
          "Cumulative rssmem shouldn't have included new processes",
          cumuRssMem,
          processTree.getCumulativeRssmem(1));

      // no processes older than 3 iterations, this should be 0
      Assert.assertEquals(
          "Getting non-zero vmem for processes older than 3 iterations",
          0L,
          processTree.getCumulativeVmem(3));
      Assert.assertEquals(
          "Getting non-zero rssmem for processes older than 3 iterations",
          0L,
          processTree.getCumulativeRssmem(3));
    } finally {
      FileUtil.fullyDelete(procfsRootDir);
    }
  }
コード例 #6
0
  /**
   * A basic test that creates a few process directories and writes stat files. Verifies that the
   * cpu time and memory is correctly computed.
   *
   * @throws IOException if there was a problem setting up the fake procfs directories or files.
   */
  @Test
  public void testCpuAndMemoryForProcessTree() throws IOException {

    // test processes
    String[] pids = {"100", "200", "300", "400"};
    // create the fake procfs root directory.
    File procfsRootDir = new File(TEST_ROOT_DIR, "proc");

    try {
      setupProcfsRootDir(procfsRootDir);
      setupPidDirs(procfsRootDir, pids);

      // create stat objects.
      // assuming processes 100, 200, 300 are in tree and 400 is not.
      ProcessStatInfo[] procInfos = new ProcessStatInfo[4];
      procInfos[0] =
          new ProcessStatInfo(
              new String[] {"100", "proc1", "1", "100", "100", "100000", "100", "1000", "200"});
      procInfos[1] =
          new ProcessStatInfo(
              new String[] {"200", "proc2", "100", "100", "100", "200000", "200", "2000", "400"});
      procInfos[2] =
          new ProcessStatInfo(
              new String[] {"300", "proc3", "200", "100", "100", "300000", "300", "3000", "600"});
      procInfos[3] =
          new ProcessStatInfo(
              new String[] {"400", "proc4", "1", "400", "400", "400000", "400", "4000", "800"});

      writeStatFiles(procfsRootDir, pids, procInfos);

      // crank up the process tree class.
      ProcfsBasedProcessTree processTree =
          createProcessTree("100", procfsRootDir.getAbsolutePath());
      // build the process tree.
      processTree.getProcessTree();

      // verify cumulative memory
      Assert.assertEquals(
          "Cumulative virtual memory does not match", 600000L, processTree.getCumulativeVmem());

      // verify rss memory
      long cumuRssMem =
          ProcfsBasedProcessTree.PAGE_SIZE > 0 ? 600L * ProcfsBasedProcessTree.PAGE_SIZE : 0L;
      Assert.assertEquals(
          "Cumulative rss memory does not match", cumuRssMem, processTree.getCumulativeRssmem());

      // verify cumulative cpu time
      long cumuCpuTime =
          ProcfsBasedProcessTree.JIFFY_LENGTH_IN_MILLIS > 0
              ? 7200L * ProcfsBasedProcessTree.JIFFY_LENGTH_IN_MILLIS
              : 0L;
      Assert.assertEquals(
          "Cumulative cpu time does not match", cumuCpuTime, processTree.getCumulativeCpuTime());

      // test the cpu time again to see if it cumulates
      procInfos[0] =
          new ProcessStatInfo(
              new String[] {"100", "proc1", "1", "100", "100", "100000", "100", "2000", "300"});
      procInfos[1] =
          new ProcessStatInfo(
              new String[] {"200", "proc2", "100", "100", "100", "200000", "200", "3000", "500"});
      writeStatFiles(procfsRootDir, pids, procInfos);

      // build the process tree.
      processTree.getProcessTree();

      // verify cumulative cpu time again
      cumuCpuTime =
          ProcfsBasedProcessTree.JIFFY_LENGTH_IN_MILLIS > 0
              ? 9400L * ProcfsBasedProcessTree.JIFFY_LENGTH_IN_MILLIS
              : 0L;
      Assert.assertEquals(
          "Cumulative cpu time does not match", cumuCpuTime, processTree.getCumulativeCpuTime());
    } finally {
      FileUtil.fullyDelete(procfsRootDir);
    }
  }