Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9cb2e2eb authored by Josh Gao's avatar Josh Gao
Browse files

libprocinfo: add support for parsing process state.

Bug: http://b/63008395
Test: libprocinfo_test32
Change-Id: I20a337bb5075bcdb325d2b48e174b0b5ef896261
parent 3e8d9232
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -35,8 +35,18 @@ namespace procinfo {

#if defined(__linux__)

enum ProcessState {
  kProcessStateUnknown,
  kProcessStateRunning,
  kProcessStateSleeping,
  kProcessStateUninterruptibleWait,
  kProcessStateStopped,
  kProcessStateZombie,
};

struct ProcessInfo {
  std::string name;
  ProcessState state;
  pid_t tid;
  pid_t pid;
  pid_t ppid;
+22 −1
Original line number Diff line number Diff line
@@ -44,6 +44,24 @@ bool GetProcessInfo(pid_t tid, ProcessInfo* process_info) {
  return GetProcessInfoFromProcPidFd(dirfd.get(), process_info);
}

static ProcessState parse_state(const char* state) {
  switch (*state) {
    case 'R':
      return kProcessStateRunning;
    case 'S':
      return kProcessStateSleeping;
    case 'D':
      return kProcessStateUninterruptibleWait;
    case 'T':
      return kProcessStateStopped;
    case 'Z':
      return kProcessStateZombie;
    default:
      LOG(ERROR) << "unknown process state: " << *state;
      return kProcessStateUnknown;
  }
}

bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info) {
  int status_fd = openat(fd, "status", O_RDONLY | O_CLOEXEC);

@@ -60,7 +78,7 @@ bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info) {
  }

  int field_bitmap = 0;
  static constexpr int finished_bitmap = 127;
  static constexpr int finished_bitmap = 255;
  char* line = nullptr;
  size_t len = 0;

@@ -98,6 +116,9 @@ bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info) {
    } else if (header == "Gid:") {
      process_info->gid = atoi(tab + 1);
      field_bitmap |= 64;
    } else if (header == "State:") {
      process_info->state = parse_state(tab + 1);
      field_bitmap |= 128;
    }
  }

+34 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <unistd.h>

#include <chrono>
#include <set>
#include <thread>
#include <vector>
@@ -29,6 +30,8 @@

#include <android-base/stringprintf.h>

using namespace std::chrono_literals;

#if !defined(__BIONIC__)
#include <syscall.h>
static pid_t gettid() {
@@ -82,3 +85,34 @@ TEST(process_info, process_tids_smoke) {
    }
  }).join();
}

TEST(process_info, process_state) {
  int pipefd[2];
  ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
  pid_t forkpid = fork();

  ASSERT_NE(-1, forkpid);
  if (forkpid == 0) {
    close(pipefd[1]);
    char buf;
    TEMP_FAILURE_RETRY(read(pipefd[0], &buf, 1));
    _exit(0);
  }

  // Give the child some time to get to the read.
  std::this_thread::sleep_for(100ms);

  android::procinfo::ProcessInfo procinfo;
  ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
  ASSERT_EQ(android::procinfo::kProcessStateSleeping, procinfo.state);

  ASSERT_EQ(0, kill(forkpid, SIGKILL));

  // Give the kernel some time to kill the child.
  std::this_thread::sleep_for(100ms);

  ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
  ASSERT_EQ(android::procinfo::kProcessStateZombie, procinfo.state);

  ASSERT_EQ(forkpid, waitpid(forkpid, nullptr, 0));
}