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

Commit 14e36421 authored by Josh Gao's avatar Josh Gao Committed by android-build-merger
Browse files

Merge changes I5c6bf2a5,I20a337bb

am: 7f81b2af

Change-Id: I5388b048cdcc41d374b1d58476def364409b72b2
parents ec8a5f2a 7f81b2af
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -274,6 +274,7 @@ cc_binary {
        "libbase",
        "libdebuggerd_client",
        "liblog",
        "libprocinfo",
        "libselinux",
    ],

+19 −0
Original line number Diff line number Diff line
@@ -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"

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