• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "process_info.h"
6 
7 #include <ctype.h>
8 #include <dirent.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 
13 #include "file_utils.h"
14 #include "logging.h"
15 
ProcessInfo(int pid)16 ProcessInfo::ProcessInfo(int pid) : memory_(pid), pid_(pid) {}
17 
IsProcess(int pid)18 bool ProcessInfo::IsProcess(int pid) {
19   char buf[256];
20   ssize_t rsize = file_utils::ReadProcFile(pid, "status", buf, sizeof(buf));
21   if (rsize <= 0)
22     return false;
23   const char kTgid[] = "\nTgid:";
24   const char* tgid_line = strstr(buf, kTgid);
25   CHECK(tgid_line);
26   int tgid = 0;
27   if (sscanf(tgid_line + strlen(kTgid), "%d", &tgid) != 1)
28     CHECK(false);
29   return tgid == pid;
30 }
31 
ReadProcessName()32 bool ProcessInfo::ReadProcessName() {
33   if (!file_utils::ReadProcFileTrimmed(pid_, "cmdline", name_, sizeof(name_)))
34     return false;
35 
36   // Fallback on "comm" for kernel threads.
37   if (strlen(name_) == 0) {
38     if (!file_utils::ReadProcFileTrimmed(pid_, "comm", name_, sizeof(name_)))
39       return false;
40   }
41 
42   // Get also the exe path, to distinguish system vs java apps and bitness.
43   char exe_path[64];
44   sprintf(exe_path, "/proc/%d/exe", pid_);
45   exe_[0] = '\0';
46   ssize_t res = readlink(exe_path, exe_, sizeof(exe_) - 1);
47   if (res >= 0)
48     exe_[res] = '\0';
49 
50   return true;
51 }
52 
ReadThreadNames()53 bool ProcessInfo::ReadThreadNames() {
54   char tasks_path[64];
55   sprintf(tasks_path, "/proc/%d/task", pid_);
56   CHECK(threads_.empty());
57   ThreadInfoMap* threads = &threads_;
58   const int pid = pid_;
59   file_utils::ForEachPidInProcPath(tasks_path, [pid, threads](int tid) {
60     char comm[64];
61     std::unique_ptr<ThreadInfo> thread_info(new ThreadInfo());
62     sprintf(comm, "task/%d/comm", tid);
63     if (!file_utils::ReadProcFileTrimmed(pid, comm, thread_info->name,
64                                          sizeof(thread_info->name))) {
65       return;
66     }
67     (*threads)[tid] = std::move(thread_info);
68   });
69   return true;
70 }
71 
ReadOOMStats()72 bool ProcessInfo::ReadOOMStats() {
73   char buf[512];
74   if (file_utils::ReadProcFileTrimmed(pid_, "oom_adj", buf, sizeof(buf)))
75     oom_adj_ = atoi(buf);
76   else
77     return false;
78 
79   if (file_utils::ReadProcFileTrimmed(pid_, "oom_score", buf, sizeof(buf)))
80     oom_score_ = atoi(buf);
81   else
82     return false;
83 
84   if (file_utils::ReadProcFileTrimmed(pid_, "oom_score_adj", buf, sizeof(buf)))
85     oom_score_adj_ = atoi(buf);
86   else
87     return false;
88 
89   return true;
90 }
91 
ReadPageFaultsAndCPUTimeStats()92 bool ProcessInfo::ReadPageFaultsAndCPUTimeStats() {
93   char buf[512];
94   if (!file_utils::ReadProcFileTrimmed(pid_, "stat", buf, sizeof(buf)))
95     return false;
96   int ret = sscanf(buf,
97                    "%*d (%*[^)]) %*c %*d %*d %*d %*d %*d %*u %lu %*lu "
98                    "%lu %*lu %lu %lu %*ld %*ld %*ld %*ld %*ld %*ld %llu",
99                    &minflt_, &majflt_, &utime_, &stime_, &start_time_);
100   CHECK(ret == 5);
101   return true;
102 }
103