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