diff options
author | Josh Gao | 2017-06-27 16:06:19 -0500 |
---|---|---|
committer | Josh Gao | 2017-06-27 17:06:27 -0500 |
commit | 9cb2e2eb8cefcfca5133d01f29ab29005e1f2a46 (patch) | |
tree | ae94fdbeda8f092eafb93313ecc0d2a29d8f947c | |
parent | 3e8d923276f0c872dc5dfd19a53d462196298267 (diff) | |
download | platform-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.h | 10 | ||||
-rw-r--r-- | libprocinfo/process.cpp | 23 | ||||
-rw-r--r-- | libprocinfo/process_test.cpp | 34 |
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 | ||
38 | enum ProcessState { | ||
39 | kProcessStateUnknown, | ||
40 | kProcessStateRunning, | ||
41 | kProcessStateSleeping, | ||
42 | kProcessStateUninterruptibleWait, | ||
43 | kProcessStateStopped, | ||
44 | kProcessStateZombie, | ||
45 | }; | ||
46 | |||
38 | struct ProcessInfo { | 47 | struct 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 | ||
47 | static 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 | |||
47 | bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info) { | 65 | bool 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 | ||
33 | using namespace std::chrono_literals; | ||
34 | |||
32 | #if !defined(__BIONIC__) | 35 | #if !defined(__BIONIC__) |
33 | #include <syscall.h> | 36 | #include <syscall.h> |
34 | static pid_t gettid() { | 37 | static pid_t gettid() { |
@@ -82,3 +85,34 @@ TEST(process_info, process_tids_smoke) { | |||
82 | } | 85 | } |
83 | }).join(); | 86 | }).join(); |
84 | } | 87 | } |
88 | |||
89 | TEST(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 | } | ||