| OLD | NEW |
| 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 "chrome/browser/process_info_snapshot.h" | 5 #include "chrome/browser/process_info_snapshot.h" |
| 6 | 6 |
| 7 #include <sys/sysctl.h> | 7 #include <sys/sysctl.h> |
| 8 | 8 |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 | 120 |
| 121 return true; | 121 return true; |
| 122 } | 122 } |
| 123 | 123 |
| 124 // Capture the information by calling '/bin/ps'. | 124 // Capture the information by calling '/bin/ps'. |
| 125 // Note: we ignore the "tsiz" (text size) display option of ps because it's | 125 // Note: we ignore the "tsiz" (text size) display option of ps because it's |
| 126 // always zero (tested on 10.5 and 10.6). | 126 // always zero (tested on 10.5 and 10.6). |
| 127 static bool GetProcessMemoryInfoUsingPS( | 127 static bool GetProcessMemoryInfoUsingPS( |
| 128 const std::vector<base::ProcessId>& pid_list, | 128 const std::vector<base::ProcessId>& pid_list, |
| 129 std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { | 129 std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { |
| 130 const char kPsPathName[] = "/bin/ps"; | 130 const FilePath kProgram("/bin/ps"); |
| 131 std::vector<std::string> argv; | 131 CommandLine command_line(kProgram); |
| 132 argv.push_back(kPsPathName); | |
| 133 | 132 |
| 134 // Get resident set size, virtual memory size. | 133 // Get resident set size, virtual memory size. |
| 135 argv.push_back("-o"); | 134 command_line.AppendArg("-o"); |
| 136 argv.push_back("pid=,rss=,vsz="); | 135 command_line.AppendArg("pid=,rss=,vsz="); |
| 137 // Only display the specified PIDs. | 136 // Only display the specified PIDs. |
| 138 for (std::vector<base::ProcessId>::const_iterator it = pid_list.begin(); | 137 for (std::vector<base::ProcessId>::const_iterator it = pid_list.begin(); |
| 139 it != pid_list.end(); ++it) { | 138 it != pid_list.end(); ++it) { |
| 140 argv.push_back("-p"); | 139 command_line.AppendArg("-p"); |
| 141 argv.push_back(base::Int64ToString(static_cast<int64>(*it))); | 140 command_line.AppendArg(base::Int64ToString(static_cast<int64>(*it))); |
| 142 } | 141 } |
| 143 | 142 |
| 144 std::string output; | 143 std::string output; |
| 145 CommandLine command_line(argv); | |
| 146 // Limit output read to a megabyte for safety. | 144 // Limit output read to a megabyte for safety. |
| 147 if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { | 145 if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { |
| 148 LOG(ERROR) << "Failure running " << kPsPathName << " to acquire data."; | 146 LOG(ERROR) << "Failure running " << kProgram.value() << " to acquire data."; |
| 149 return false; | 147 return false; |
| 150 } | 148 } |
| 151 | 149 |
| 152 std::istringstream in(output, std::istringstream::in); | 150 std::istringstream in(output, std::istringstream::in); |
| 153 std::string line; | 151 std::string line; |
| 154 | 152 |
| 155 // Process lines until done. | 153 // Process lines until done. |
| 156 while (true) { | 154 while (true) { |
| 157 // The format is as specified above to ps (see ps(1)): | 155 // The format is as specified above to ps (see ps(1)): |
| 158 // "-o pid=,rss=,vsz=". | 156 // "-o pid=,rss=,vsz=". |
| 159 // Try to read the PID; if we get it, we should be able to get the rest of | 157 // Try to read the PID; if we get it, we should be able to get the rest of |
| 160 // the line. | 158 // the line. |
| 161 pid_t pid; | 159 pid_t pid; |
| 162 in >> pid; | 160 in >> pid; |
| 163 if (in.eof()) | 161 if (in.eof()) |
| 164 break; | 162 break; |
| 165 | 163 |
| 166 ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid]; | 164 ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid]; |
| 167 proc_info.pid = pid; | 165 proc_info.pid = pid; |
| 168 in >> proc_info.rss; | 166 in >> proc_info.rss; |
| 169 in >> proc_info.vsize; | 167 in >> proc_info.vsize; |
| 170 proc_info.rss *= 1024; // Convert from kilobytes to bytes. | 168 proc_info.rss *= 1024; // Convert from kilobytes to bytes. |
| 171 proc_info.vsize *= 1024; | 169 proc_info.vsize *= 1024; |
| 172 in.ignore(1, ' '); // Eat the space. | 170 in.ignore(1, ' '); // Eat the space. |
| 173 std::getline(in, proc_info.command); // Get the rest of the line. | 171 std::getline(in, proc_info.command); // Get the rest of the line. |
| 174 if (!in.good()) { | 172 if (!in.good()) { |
| 175 LOG(ERROR) << "Error parsing output from " << kPsPathName << "."; | 173 LOG(ERROR) << "Error parsing output from " << kProgram.value() << "."; |
| 176 return false; | 174 return false; |
| 177 } | 175 } |
| 178 | 176 |
| 179 if (!proc_info.pid || ! proc_info.vsize) { | 177 if (!proc_info.pid || ! proc_info.vsize) { |
| 180 LOG(WARNING) << "Invalid data from " << kPsPathName << "."; | 178 LOG(WARNING) << "Invalid data from " << kProgram.value() << "."; |
| 181 return false; | 179 return false; |
| 182 } | 180 } |
| 183 | 181 |
| 184 // Record the process information. | 182 // Record the process information. |
| 185 proc_info_entries[proc_info.pid] = proc_info; | 183 proc_info_entries[proc_info.pid] = proc_info; |
| 186 } | 184 } |
| 187 | 185 |
| 188 return true; | 186 return true; |
| 189 } | 187 } |
| 190 | 188 |
| 191 static bool GetProcessMemoryInfoUsingTop( | 189 static bool GetProcessMemoryInfoUsingTop( |
| 192 std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { | 190 std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { |
| 193 const char kTopPathName[] = "/usr/bin/top"; | 191 const FilePath kProgram("/usr/bin/top"); |
| 194 std::vector<std::string> argv; | 192 CommandLine command_line(kProgram); |
| 195 argv.push_back(kTopPathName); | |
| 196 | 193 |
| 197 // -stats tells top to print just the given fields as ordered. | 194 // -stats tells top to print just the given fields as ordered. |
| 198 argv.push_back("-stats"); | 195 command_line.AppendArg("-stats"); |
| 199 argv.push_back("pid," // Process ID | 196 command_line.AppendArg("pid," // Process ID |
| 200 "rsize," // Resident memory | 197 "rsize," // Resident memory |
| 201 "rshrd," // Resident shared memory | 198 "rshrd," // Resident shared memory |
| 202 "rprvt," // Resident private memory | 199 "rprvt," // Resident private memory |
| 203 "vsize"); // Total virtual memory | 200 "vsize"); // Total virtual memory |
| 204 // Run top in logging (non-interactive) mode. | 201 // Run top in logging (non-interactive) mode. |
| 205 argv.push_back("-l"); | 202 command_line.AppendArg("-l"); |
| 206 argv.push_back("1"); | 203 command_line.AppendArg("1"); |
| 207 // Set the delay between updates to 0. | 204 // Set the delay between updates to 0. |
| 208 argv.push_back("-s"); | 205 command_line.AppendArg("-s"); |
| 209 argv.push_back("0"); | 206 command_line.AppendArg("0"); |
| 210 | 207 |
| 211 std::string output; | 208 std::string output; |
| 212 CommandLine command_line(argv); | |
| 213 // Limit output read to a megabyte for safety. | 209 // Limit output read to a megabyte for safety. |
| 214 if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { | 210 if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { |
| 215 LOG(ERROR) << "Failure running " << kTopPathName << " to acquire data."; | 211 LOG(ERROR) << "Failure running " << kProgram.value() << " to acquire data."; |
| 216 return false; | 212 return false; |
| 217 } | 213 } |
| 218 | 214 |
| 219 // Process lines until done. Lines should look something like this: | 215 // Process lines until done. Lines should look something like this: |
| 220 // PID RSIZE RSHRD RPRVT VSIZE | 216 // PID RSIZE RSHRD RPRVT VSIZE |
| 221 // 58539 1276K+ 336K+ 740K+ 2378M+ | 217 // 58539 1276K+ 336K+ 740K+ 2378M+ |
| 222 // 58485 1888K+ 592K+ 1332K+ 2383M+ | 218 // 58485 1888K+ 592K+ 1332K+ 2383M+ |
| 223 std::istringstream top_in(output, std::istringstream::in); | 219 std::istringstream top_in(output, std::istringstream::in); |
| 224 std::string line; | 220 std::string line; |
| 225 while (std::getline(top_in, line)) { | 221 while (std::getline(top_in, line)) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 proc_info.vsize = values[3]; | 263 proc_info.vsize = values[3]; |
| 268 // Record the process information. | 264 // Record the process information. |
| 269 proc_info_entries[proc_info.pid] = proc_info; | 265 proc_info_entries[proc_info.pid] = proc_info; |
| 270 } | 266 } |
| 271 | 267 |
| 272 return true; | 268 return true; |
| 273 } | 269 } |
| 274 | 270 |
| 275 static bool GetProcessMemoryInfoUsingTop_10_5( | 271 static bool GetProcessMemoryInfoUsingTop_10_5( |
| 276 std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { | 272 std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { |
| 277 const char kTopPathName[] = "/usr/bin/top"; | 273 const FilePath kProgram("/usr/bin/top"); |
| 278 std::vector<std::string> argv; | 274 CommandLine command_line(kProgram); |
| 279 argv.push_back(kTopPathName); | |
| 280 | 275 |
| 281 // -p tells top to print just the given fields as ordered. | 276 // -p tells top to print just the given fields as ordered. |
| 282 argv.push_back("-p"); | 277 command_line.AppendArg("-p"); |
| 283 argv.push_back("^aaaaaaaaaaaaaaaaaaaa " // Process ID (PID) | 278 command_line.AppendArg( |
| 284 "^jjjjjjjjjjjjjjjjjjjj " // Resident memory (RSIZE) | 279 "^aaaaaaaaaaaaaaaaaaaa " // Process ID (PID) |
| 285 "^iiiiiiiiiiiiiiiiiiii " // Resident shared memory (RSHRD) | 280 "^jjjjjjjjjjjjjjjjjjjj " // Resident memory (RSIZE) |
| 286 "^hhhhhhhhhhhhhhhhhhhh " // Resident private memory (RPRVT) | 281 "^iiiiiiiiiiiiiiiiiiii " // Resident shared memory (RSHRD) |
| 287 "^llllllllllllllllllll"); // Total virtual memory (VSIZE) | 282 "^hhhhhhhhhhhhhhhhhhhh " // Resident private memory (RPRVT) |
| 283 "^llllllllllllllllllll"); // Total virtual memory (VSIZE) |
| 288 // Run top in logging (non-interactive) mode. | 284 // Run top in logging (non-interactive) mode. |
| 289 argv.push_back("-l"); | 285 command_line.AppendArg("-l"); |
| 290 argv.push_back("1"); | 286 command_line.AppendArg("1"); |
| 291 // Set the delay between updates to 0. | 287 // Set the delay between updates to 0. |
| 292 argv.push_back("-s"); | 288 command_line.AppendArg("-s"); |
| 293 argv.push_back("0"); | 289 command_line.AppendArg("0"); |
| 294 | 290 |
| 295 std::string output; | 291 std::string output; |
| 296 CommandLine command_line(argv); | |
| 297 // Limit output read to a megabyte for safety. | 292 // Limit output read to a megabyte for safety. |
| 298 if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { | 293 if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { |
| 299 LOG(ERROR) << "Failure running " << kTopPathName << " to acquire data."; | 294 LOG(ERROR) << "Failure running " << kProgram.value() << " to acquire data."; |
| 300 return false; | 295 return false; |
| 301 } | 296 } |
| 302 | 297 |
| 303 // Process lines until done. Lines should look something like this: | 298 // Process lines until done. Lines should look something like this: |
| 304 // PID RSIZE RSHRD RPRVT VSIZE | 299 // PID RSIZE RSHRD RPRVT VSIZE |
| 305 // 16943 815104 262144 290816 18489344 | 300 // 16943 815104 262144 290816 18489344 |
| 306 // 16922 954368 720896 278528 18976768 | 301 // 16922 954368 720896 278528 18976768 |
| 307 std::istringstream top_in(output, std::istringstream::in); | 302 std::istringstream top_in(output, std::istringstream::in); |
| 308 std::string line; | 303 std::string line; |
| 309 while (std::getline(top_in, line)) { | 304 while (std::getline(top_in, line)) { |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 ws_usage->shareable = 0; | 451 ws_usage->shareable = 0; |
| 457 ws_usage->shared = 0; | 452 ws_usage->shared = 0; |
| 458 return false; | 453 return false; |
| 459 } | 454 } |
| 460 | 455 |
| 461 ws_usage->priv = proc_info.rprvt / 1024; | 456 ws_usage->priv = proc_info.rprvt / 1024; |
| 462 ws_usage->shareable = proc_info.rss / 1024; | 457 ws_usage->shareable = proc_info.rss / 1024; |
| 463 ws_usage->shared = proc_info.rshrd / 1024; | 458 ws_usage->shared = proc_info.rshrd / 1024; |
| 464 return true; | 459 return true; |
| 465 } | 460 } |
| OLD | NEW |