summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Gao2017-06-27 16:06:19 -0500
committerJosh Gao2017-06-27 17:06:27 -0500
commit9cb2e2eb8cefcfca5133d01f29ab29005e1f2a46 (patch)
treeae94fdbeda8f092eafb93313ecc0d2a29d8f947c
parent3e8d923276f0c872dc5dfd19a53d462196298267 (diff)
downloadplatform-system-core-9cb2e2eb8cefcfca5133d01f29ab29005e1f2a46.tar.gz
platform-system-core-9cb2e2eb8cefcfca5133d01f29ab29005e1f2a46.tar.xz
platform-system-core-9cb2e2eb8cefcfca5133d01f29ab29005e1f2a46.zip
libprocinfo: add support for parsing process state.
Bug: http://b/63008395 Test: libprocinfo_test32 Change-Id: I20a337bb5075bcdb325d2b48e174b0b5ef896261
-rw-r--r--libprocinfo/include/procinfo/process.h10
-rw-r--r--libprocinfo/process.cpp23
-rw-r--r--libprocinfo/process_test.cpp34
3 files changed, 66 insertions, 1 deletions
diff --git a/libprocinfo/include/procinfo/process.h b/libprocinfo/include/procinfo/process.h
index fb140ff3d..db56fc1a5 100644
--- a/libprocinfo/include/procinfo/process.h
+++ b/libprocinfo/include/procinfo/process.h
@@ -35,8 +35,18 @@ namespace procinfo {
35 35
36#if defined(__linux__) 36#if defined(__linux__)
37 37
38enum ProcessState {
39 kProcessStateUnknown,
40 kProcessStateRunning,
41 kProcessStateSleeping,
42 kProcessStateUninterruptibleWait,
43 kProcessStateStopped,
44 kProcessStateZombie,
45};
46
38struct ProcessInfo { 47struct ProcessInfo {
39 std::string name; 48 std::string name;
49 ProcessState state;
40 pid_t tid; 50 pid_t tid;
41 pid_t pid; 51 pid_t pid;
42 pid_t ppid; 52 pid_t ppid;
diff --git a/libprocinfo/process.cpp b/libprocinfo/process.cpp
index c513e16f5..6e5be6e56 100644
--- a/libprocinfo/process.cpp
+++ b/libprocinfo/process.cpp
@@ -44,6 +44,24 @@ bool GetProcessInfo(pid_t tid, ProcessInfo* process_info) {
44 return GetProcessInfoFromProcPidFd(dirfd.get(), process_info); 44 return GetProcessInfoFromProcPidFd(dirfd.get(), process_info);
45} 45}
46 46
47static ProcessState parse_state(const char* state) {
48 switch (*state) {
49 case 'R':
50 return kProcessStateRunning;
51 case 'S':
52 return kProcessStateSleeping;
53 case 'D':
54 return kProcessStateUninterruptibleWait;
55 case 'T':
56 return kProcessStateStopped;
57 case 'Z':
58 return kProcessStateZombie;
59 default:
60 LOG(ERROR) << "unknown process state: " << *state;
61 return kProcessStateUnknown;
62 }
63}
64
47bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info) { 65bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info) {
48 int status_fd = openat(fd, "status", O_RDONLY | O_CLOEXEC); 66 int status_fd = openat(fd, "status", O_RDONLY | O_CLOEXEC);
49 67
@@ -60,7 +78,7 @@ bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info) {
60 } 78 }
61 79
62 int field_bitmap = 0; 80 int field_bitmap = 0;
63 static constexpr int finished_bitmap = 127; 81 static constexpr int finished_bitmap = 255;
64 char* line = nullptr; 82 char* line = nullptr;
65 size_t len = 0; 83 size_t len = 0;
66 84
@@ -98,6 +116,9 @@ bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info) {
98 } else if (header == "Gid:") { 116 } else if (header == "Gid:") {
99 process_info->gid = atoi(tab + 1); 117 process_info->gid = atoi(tab + 1);
100 field_bitmap |= 64; 118 field_bitmap |= 64;
119 } else if (header == "State:") {
120 process_info->state = parse_state(tab + 1);
121 field_bitmap |= 128;
101 } 122 }
102 } 123 }
103 124
diff --git a/libprocinfo/process_test.cpp b/libprocinfo/process_test.cpp
index 5ffd2365b..9da927899 100644
--- a/libprocinfo/process_test.cpp
+++ b/libprocinfo/process_test.cpp
@@ -21,6 +21,7 @@
21#include <sys/types.h> 21#include <sys/types.h>
22#include <unistd.h> 22#include <unistd.h>
23 23
24#include <chrono>
24#include <set> 25#include <set>
25#include <thread> 26#include <thread>
26#include <vector> 27#include <vector>
@@ -29,6 +30,8 @@
29 30
30#include <android-base/stringprintf.h> 31#include <android-base/stringprintf.h>
31 32
33using namespace std::chrono_literals;
34
32#if !defined(__BIONIC__) 35#if !defined(__BIONIC__)
33#include <syscall.h> 36#include <syscall.h>
34static pid_t gettid() { 37static pid_t gettid() {
@@ -82,3 +85,34 @@ TEST(process_info, process_tids_smoke) {
82 } 85 }
83 }).join(); 86 }).join();
84} 87}
88
89TEST(process_info, process_state) {
90 int pipefd[2];
91 ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
92 pid_t forkpid = fork();
93
94 ASSERT_NE(-1, forkpid);
95 if (forkpid == 0) {
96 close(pipefd[1]);
97 char buf;
98 TEMP_FAILURE_RETRY(read(pipefd[0], &buf, 1));
99 _exit(0);
100 }
101
102 // Give the child some time to get to the read.
103 std::this_thread::sleep_for(100ms);
104
105 android::procinfo::ProcessInfo procinfo;
106 ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
107 ASSERT_EQ(android::procinfo::kProcessStateSleeping, procinfo.state);
108
109 ASSERT_EQ(0, kill(forkpid, SIGKILL));
110
111 // Give the kernel some time to kill the child.
112 std::this_thread::sleep_for(100ms);
113
114 ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
115 ASSERT_EQ(android::procinfo::kProcessStateZombie, procinfo.state);
116
117 ASSERT_EQ(forkpid, waitpid(forkpid, nullptr, 0));
118}