| Index: chrome/browser/process_info_snapshot_mac.cc
|
| diff --git a/chrome/browser/process_info_snapshot_mac.cc b/chrome/browser/process_info_snapshot_mac.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..801ebe0eeb4264e35fe876660bf2f794f0cb4bd3
|
| --- /dev/null
|
| +++ b/chrome/browser/process_info_snapshot_mac.cc
|
| @@ -0,0 +1,154 @@
|
| +// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/process_info_snapshot.h"
|
| +
|
| +#include <iostream>
|
| +#include <sstream>
|
| +
|
| +#include "base/string_util.h"
|
| +#include "base/thread.h"
|
| +
|
| +// Implementation for the Mac; calls '/bin/ps' for information when
|
| +// |Sample()| is called.
|
| +
|
| +// Default constructor.
|
| +ProcessInfoSnapshot::ProcessInfoSnapshot() { }
|
| +
|
| +// Destructor: just call |Reset()| to release everything.
|
| +ProcessInfoSnapshot::~ProcessInfoSnapshot() {
|
| + Reset();
|
| +}
|
| +
|
| +// Capture the information by calling '/bin/ps'.
|
| +// Note: we ignore the "tsiz" (text size) display option of ps because it's
|
| +// always zero (tested on 10.5 and 10.6).
|
| +bool ProcessInfoSnapshot::Sample(std::vector<base::ProcessId> pid_list) {
|
| + Reset();
|
| +
|
| + std::vector<std::string> argv;
|
| + argv.push_back("/bin/ps");
|
| + // Get PID, PPID, (real) UID, effective UID, resident set size, virtual memory
|
| + // size, and command.
|
| + argv.push_back("-o");
|
| + argv.push_back("pid=,ppid=,ruid=,uid=,rss=,vsz=,comm=");
|
| + // Only display the specified PIDs.
|
| + for(std::vector<base::ProcessId>::iterator it = pid_list.begin();
|
| + it != pid_list.end(); ++it) {
|
| + argv.push_back("-p");
|
| + argv.push_back(Int64ToString(static_cast<int64>(*it)));
|
| + }
|
| +
|
| + std::string output;
|
| + CommandLine command_line(argv);
|
| + if (!base::GetAppOutputRestricted(command_line,
|
| + &output, (pid_list.size() + 10) * 100)) {
|
| + LOG(ERROR) << "Failure running /bin/ps to acquire data.";
|
| + return false;
|
| + }
|
| +
|
| + std::istringstream in(output, std::istringstream::in);
|
| + std::string line;
|
| +
|
| + // Process lines until done.
|
| + while (true) {
|
| + ProcInfoEntry proc_info;
|
| +
|
| + // See the constructor (and top(1)) for the expected format. Try to read the
|
| + // PID; if we get it, we should be able to get the rest of the line.
|
| + in >> proc_info.pid;
|
| + if (in.eof())
|
| + break;
|
| + in >> proc_info.ppid;
|
| + in >> proc_info.uid;
|
| + in >> proc_info.euid;
|
| + in >> proc_info.rss;
|
| + in >> proc_info.vsize;
|
| + in.ignore(1, ' '); // Eat the space.
|
| + std::getline(in, proc_info.command); // Get the rest of the line.
|
| + if (!in.good()) {
|
| + LOG(ERROR) << "Error parsing output from /usr/bin/top.";
|
| + return false;
|
| + }
|
| +
|
| + // Make sure the new PID isn't already in our list.
|
| + if (proc_info_entries_.find(proc_info.pid) != proc_info_entries_.end()) {
|
| + LOG(ERROR) << "Duplicate PID in output from /bin/ps.";
|
| + return false;
|
| + }
|
| +
|
| + if (!proc_info.pid || ! proc_info.vsize) {
|
| + LOG(WARNING) << "Invalid data from /bin/ps.";
|
| + return false;
|
| + }
|
| +
|
| + // Record the process information.
|
| + proc_info_entries_[proc_info.pid] = proc_info;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +// Clear all the stored information.
|
| +void ProcessInfoSnapshot::Reset() {
|
| + proc_info_entries_.clear();
|
| +}
|
| +
|
| +bool ProcessInfoSnapshot::GetProcInfo(int pid,
|
| + ProcInfoEntry* proc_info) const {
|
| + std::map<int,ProcInfoEntry>::const_iterator it = proc_info_entries_.find(pid);
|
| + if (it == proc_info_entries_.end())
|
| + return false;
|
| +
|
| + *proc_info = it->second;
|
| + return true;
|
| +}
|
| +
|
| +bool ProcessInfoSnapshot::GetCommittedKBytesOfPID(
|
| + int pid,
|
| + base::CommittedKBytes* usage) const {
|
| + // Try to avoid crashing on a bug; stats aren't usually so crucial.
|
| + if (!usage) {
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| +
|
| + // Failure of |GetProcInfo()| is "normal", due to racing.
|
| + ProcInfoEntry proc_info;
|
| + if (!GetProcInfo(pid, &proc_info)) {
|
| + usage->priv = 0;
|
| + usage->mapped = 0;
|
| + usage->image = 0;
|
| + return false;
|
| + }
|
| +
|
| + usage->priv = proc_info.vsize;
|
| + usage->mapped = 0;
|
| + usage->image = 0;
|
| + return true;
|
| +}
|
| +
|
| +bool ProcessInfoSnapshot::GetWorkingSetKBytesOfPID(
|
| + int pid,
|
| + base::WorkingSetKBytes* ws_usage) const {
|
| + // Try to avoid crashing on a bug; stats aren't usually so crucial.
|
| + if (!ws_usage) {
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| +
|
| + // Failure of |GetProcInfo()| is "normal", due to racing.
|
| + ProcInfoEntry proc_info;
|
| + if (!GetProcInfo(pid, &proc_info)) {
|
| + ws_usage->priv = 0;
|
| + ws_usage->shareable = 0;
|
| + ws_usage->shared = 0;
|
| + return false;
|
| + }
|
| +
|
| + ws_usage->priv = 0;
|
| + ws_usage->shareable = proc_info.rss;
|
| + ws_usage->shared = 0;
|
| + return true;
|
| +}
|
|
|