Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(594)

Side by Side Diff: base/process_util_linux.cc

Issue 1689012: Move common code into process_util.cc (Closed)
Patch Set: More fixes Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/process_util.cc ('k') | base/process_util_mac.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/process_util.h" 5 #include "base/process_util.h"
6 6
7 #include <ctype.h> 7 #include <ctype.h>
8 #include <dirent.h> 8 #include <dirent.h>
9 #include <dlfcn.h> 9 #include <dlfcn.h>
10 #include <errno.h> 10 #include <errno.h>
11 #include <fcntl.h> 11 #include <fcntl.h>
12 #include <sys/time.h> 12 #include <sys/time.h>
13 #include <sys/types.h> 13 #include <sys/types.h>
14 #include <sys/wait.h> 14 #include <sys/wait.h>
15 #include <time.h> 15 #include <time.h>
16 #include <unistd.h> 16 #include <unistd.h>
17 17
18 #include "base/file_util.h" 18 #include "base/file_util.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/string_tokenizer.h" 20 #include "base/string_tokenizer.h"
21 #include "base/string_util.h" 21 #include "base/string_util.h"
22 #include "base/sys_info.h"
22 23
23 namespace { 24 namespace {
24 25
25 enum ParsingState { 26 enum ParsingState {
26 KEY_NAME, 27 KEY_NAME,
27 KEY_VALUE 28 KEY_VALUE
28 }; 29 };
29 30
30 // Reads /proc/<pid>/stat and populates |proc_stats| with the values split by 31 // Reads /proc/<pid>/stat and populates |proc_stats| with the values split by
31 // spaces. 32 // spaces.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 stat_file = stat_file.Append("exe"); 81 stat_file = stat_file.Append("exe");
81 char exename[2048]; 82 char exename[2048];
82 ssize_t len = readlink(stat_file.value().c_str(), exename, sizeof(exename)); 83 ssize_t len = readlink(stat_file.value().c_str(), exename, sizeof(exename));
83 if (len < 1) { 84 if (len < 1) {
84 // No such process. Happens frequently in e.g. TerminateAllChromeProcesses 85 // No such process. Happens frequently in e.g. TerminateAllChromeProcesses
85 return FilePath(); 86 return FilePath();
86 } 87 }
87 return FilePath(std::string(exename, len)); 88 return FilePath(std::string(exename, len));
88 } 89 }
89 90
90 NamedProcessIterator::NamedProcessIterator(const std::wstring& executable_name, 91 ProcessIterator::ProcessIterator(const ProcessFilter* filter)
91 const ProcessFilter* filter) 92 : filter_(filter) {
92 : executable_name_(executable_name), filter_(filter) {
93 procfs_dir_ = opendir("/proc"); 93 procfs_dir_ = opendir("/proc");
94 } 94 }
95 95
96 NamedProcessIterator::~NamedProcessIterator() { 96 ProcessIterator::~ProcessIterator() {
97 if (procfs_dir_) { 97 if (procfs_dir_) {
98 closedir(procfs_dir_); 98 closedir(procfs_dir_);
99 procfs_dir_ = NULL; 99 procfs_dir_ = NULL;
100 } 100 }
101 } 101 }
102 102
103 const ProcessEntry* NamedProcessIterator::NextProcessEntry() { 103 bool ProcessIterator::CheckForNextProcess() {
104 bool result = false;
105 do {
106 result = CheckForNextProcess();
107 } while (result && !IncludeEntry());
108
109 if (result)
110 return &entry_;
111
112 return NULL;
113 }
114
115 bool NamedProcessIterator::CheckForNextProcess() {
116 // TODO(port): skip processes owned by different UID 104 // TODO(port): skip processes owned by different UID
117 105
118 dirent* slot = 0; 106 dirent* slot = 0;
119 const char* openparen; 107 const char* openparen;
120 const char* closeparen; 108 const char* closeparen;
121 109
122 // Arbitrarily guess that there will never be more than 200 non-process 110 // Arbitrarily guess that there will never be more than 200 non-process
123 // files in /proc. Hardy has 53. 111 // files in /proc. Hardy has 53.
124 int skipped = 0; 112 int skipped = 0;
125 const int kSkipLimit = 200; 113 const int kSkipLimit = 200;
(...skipping 22 matching lines...) Expand all
148 sprintf(buf, "/proc/%s/stat", slot->d_name); 136 sprintf(buf, "/proc/%s/stat", slot->d_name);
149 FILE *fp = fopen(buf, "r"); 137 FILE *fp = fopen(buf, "r");
150 if (!fp) 138 if (!fp)
151 return false; 139 return false;
152 const char* result = fgets(buf, sizeof(buf), fp); 140 const char* result = fgets(buf, sizeof(buf), fp);
153 fclose(fp); 141 fclose(fp);
154 if (!result) 142 if (!result)
155 return false; 143 return false;
156 144
157 // Parse the status. It is formatted like this: 145 // Parse the status. It is formatted like this:
158 // %d (%s) %c %d ... 146 // %d (%s) %c %d %d ...
159 // pid (name) runstate ppid 147 // pid (name) runstate ppid gid
160 // To avoid being fooled by names containing a closing paren, scan 148 // To avoid being fooled by names containing a closing paren, scan
161 // backwards. 149 // backwards.
162 openparen = strchr(buf, '('); 150 openparen = strchr(buf, '(');
163 closeparen = strrchr(buf, ')'); 151 closeparen = strrchr(buf, ')');
164 if (!openparen || !closeparen) 152 if (!openparen || !closeparen)
165 return false; 153 return false;
166 char runstate = closeparen[2]; 154 char runstate = closeparen[2];
167 155
168 // Is the process in 'Zombie' state, i.e. dead but waiting to be reaped? 156 // Is the process in 'Zombie' state, i.e. dead but waiting to be reaped?
169 // Allowed values: D R S T Z 157 // Allowed values: D R S T Z
170 if (runstate != 'Z') 158 if (runstate != 'Z')
171 break; 159 break;
172 160
173 // Nope, it's a zombie; somebody isn't cleaning up after their children. 161 // Nope, it's a zombie; somebody isn't cleaning up after their children.
174 // (e.g. WaitForProcessesToExit doesn't clean up after dead children yet.) 162 // (e.g. WaitForProcessesToExit doesn't clean up after dead children yet.)
175 // There could be a lot of zombies, can't really decrement i here. 163 // There could be a lot of zombies, can't really decrement i here.
176 } 164 }
177 if (skipped >= kSkipLimit) { 165 if (skipped >= kSkipLimit) {
178 NOTREACHED(); 166 NOTREACHED();
179 return false; 167 return false;
180 } 168 }
181 169
182 entry_.pid = atoi(slot->d_name); 170 // This seems fragile.
183 entry_.ppid = atoi(closeparen + 3); 171 entry_.pid_ = atoi(slot->d_name);
172 entry_.ppid_ = atoi(closeparen + 3);
173 entry_.gid_ = atoi(strchr(closeparen + 4, ' '));
184 174
185 // TODO(port): read pid's commandline's $0, like killall does. Using the 175 // TODO(port): read pid's commandline's $0, like killall does. Using the
186 // short name between openparen and closeparen won't work for long names! 176 // short name between openparen and closeparen won't work for long names!
187 int len = closeparen - openparen - 1; 177 int len = closeparen - openparen - 1;
188 if (len > NAME_MAX) 178 entry_.exe_file_.assign(openparen + 1, len);
189 len = NAME_MAX;
190 memcpy(entry_.szExeFile, openparen + 1, len);
191 entry_.szExeFile[len] = 0;
192
193 return true; 179 return true;
194 } 180 }
195 181
196 bool NamedProcessIterator::IncludeEntry() { 182 bool NamedProcessIterator::IncludeEntry() {
197 // TODO(port): make this also work for non-ASCII filenames 183 // TODO(port): make this also work for non-ASCII filenames
198 if (WideToASCII(executable_name_) != entry_.szExeFile) 184 if (WideToASCII(executable_name_) != entry().exe_file())
199 return false; 185 return false;
200 if (!filter_) 186 return ProcessIterator::IncludeEntry();
201 return true; 187 }
202 return filter_->Includes(entry_.pid, entry_.ppid); 188
189
190 ProcessMetrics::ProcessMetrics(ProcessHandle process)
191 : process_(process),
192 last_time_(0),
193 last_system_time_(0),
194 last_cpu_(0) {
195 processor_count_ = base::SysInfo::NumberOfProcessors();
196 }
197
198 // static
199 ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
200 return new ProcessMetrics(process);
203 } 201 }
204 202
205 // On linux, we return vsize. 203 // On linux, we return vsize.
206 size_t ProcessMetrics::GetPagefileUsage() const { 204 size_t ProcessMetrics::GetPagefileUsage() const {
207 std::vector<std::string> proc_stats; 205 std::vector<std::string> proc_stats;
208 GetProcStats(process_, &proc_stats); 206 GetProcStats(process_, &proc_stats);
209 const size_t kVmSize = 22; 207 const size_t kVmSize = 22;
210 if (proc_stats.size() > kVmSize) 208 if (proc_stats.size() > kVmSize)
211 return static_cast<size_t>(StringToInt(proc_stats[kVmSize])); 209 return static_cast<size_t>(StringToInt(proc_stats[kVmSize]));
212 return 0; 210 return 0;
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 607
610 if (!file_util::PathExists(oom_adj)) 608 if (!file_util::PathExists(oom_adj))
611 return false; 609 return false;
612 610
613 std::string score_str = IntToString(score); 611 std::string score_str = IntToString(score);
614 return (static_cast<int>(score_str.length()) == 612 return (static_cast<int>(score_str.length()) ==
615 file_util::WriteFile(oom_adj, score_str.c_str(), score_str.length())); 613 file_util::WriteFile(oom_adj, score_str.c_str(), score_str.length()));
616 } 614 }
617 615
618 } // namespace base 616 } // namespace base
OLDNEW
« no previous file with comments | « base/process_util.cc ('k') | base/process_util_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698