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 16 ProcessInfo::ProcessInfo(int pid) : memory_(pid), pid_(pid) {} 17 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 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 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 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 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