Loading debuggerd/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -274,6 +274,7 @@ cc_binary { "libbase", "libdebuggerd_client", "liblog", "libprocinfo", "libselinux", ], Loading debuggerd/debuggerd.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <android-base/parseint.h> #include <android-base/unique_fd.h> #include <debuggerd/client.h> #include <procinfo/process.h> #include <selinux/selinux.h> #include "util.h" Loading Loading @@ -66,6 +67,24 @@ int main(int argc, char* argv[]) { usage(1); } if (getuid() != 0) { errx(1, "root is required"); } // Check to see if the process exists and that we can actually send a signal to it. android::procinfo::ProcessInfo proc_info; if (!android::procinfo::GetProcessInfo(pid, &proc_info)) { err(1, "failed to fetch info for process %d", pid); } if (proc_info.state == android::procinfo::kProcessStateZombie) { errx(1, "process %d is a zombie", pid); } if (kill(pid, 0) != 0) { err(1, "cannot send signal to process %d", pid); } unique_fd piperead, pipewrite; if (!Pipe(&piperead, &pipewrite)) { err(1, "failed to create pipe"); Loading libprocinfo/include/procinfo/process.h +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading libprocinfo/process.cpp +22 −1 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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; Loading Loading @@ -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; } } Loading libprocinfo/process_test.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <sys/types.h> #include <unistd.h> #include <chrono> #include <set> #include <thread> #include <vector> Loading @@ -29,6 +30,8 @@ #include <android-base/stringprintf.h> using namespace std::chrono_literals; #if !defined(__BIONIC__) #include <syscall.h> static pid_t gettid() { Loading Loading @@ -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)); } Loading
debuggerd/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -274,6 +274,7 @@ cc_binary { "libbase", "libdebuggerd_client", "liblog", "libprocinfo", "libselinux", ], Loading
debuggerd/debuggerd.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <android-base/parseint.h> #include <android-base/unique_fd.h> #include <debuggerd/client.h> #include <procinfo/process.h> #include <selinux/selinux.h> #include "util.h" Loading Loading @@ -66,6 +67,24 @@ int main(int argc, char* argv[]) { usage(1); } if (getuid() != 0) { errx(1, "root is required"); } // Check to see if the process exists and that we can actually send a signal to it. android::procinfo::ProcessInfo proc_info; if (!android::procinfo::GetProcessInfo(pid, &proc_info)) { err(1, "failed to fetch info for process %d", pid); } if (proc_info.state == android::procinfo::kProcessStateZombie) { errx(1, "process %d is a zombie", pid); } if (kill(pid, 0) != 0) { err(1, "cannot send signal to process %d", pid); } unique_fd piperead, pipewrite; if (!Pipe(&piperead, &pipewrite)) { err(1, "failed to create pipe"); Loading
libprocinfo/include/procinfo/process.h +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
libprocinfo/process.cpp +22 −1 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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; Loading Loading @@ -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; } } Loading
libprocinfo/process_test.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <sys/types.h> #include <unistd.h> #include <chrono> #include <set> #include <thread> #include <vector> Loading @@ -29,6 +30,8 @@ #include <android-base/stringprintf.h> using namespace std::chrono_literals; #if !defined(__BIONIC__) #include <syscall.h> static pid_t gettid() { Loading Loading @@ -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)); }