libprocinfo: add support for parsing process state.

Bug: http://b/63008395
Test: libprocinfo_test32
Change-Id: I20a337bb5075bcdb325d2b48e174b0b5ef896261
This commit is contained in:
Josh Gao 2017-06-27 14:06:19 -07:00
parent 3e8d923276
commit 9cb2e2eb8c
3 changed files with 66 additions and 1 deletions

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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));
}