| Index: base/process_util_mac.mm
|
| ===================================================================
|
| --- base/process_util_mac.mm (revision 9017)
|
| +++ base/process_util_mac.mm (working copy)
|
| @@ -2,16 +2,20 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -
|
| -#include "base/logging.h"
|
| #include "base/process_util.h"
|
|
|
| #import <Cocoa/Cocoa.h>
|
| #include <spawn.h>
|
| -#include <string>
|
| +#include <sys/sysctl.h>
|
| #include <sys/types.h>
|
| #include <sys/wait.h>
|
|
|
| +#include <string>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/string_util.h"
|
| +#include "base/time.h"
|
| +
|
| extern "C" {
|
| extern char** environ;
|
| }
|
| @@ -76,7 +80,7 @@
|
| if (wait)
|
| waitpid(pid, 0, 0);
|
|
|
| - if(process_handle)
|
| + if (process_handle)
|
| *process_handle = pid;
|
| }
|
|
|
| @@ -90,21 +94,107 @@
|
| return LaunchApp(cl.argv(), no_files, wait, process_handle);
|
| }
|
|
|
| -bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) {
|
| - // TODO(pinkerton): can we implement this? On linux it relies on /proc.
|
| - return false;
|
| +NamedProcessIterator::NamedProcessIterator(const std::wstring& executable_name,
|
| + const ProcessFilter* filter)
|
| + : executable_name_(executable_name),
|
| + index_of_kinfo_proc_(0),
|
| + filter_(filter) {
|
| }
|
|
|
| -int GetProcessCount(const std::wstring& executable_name,
|
| - const ProcessFilter* filter) {
|
| - NOTIMPLEMENTED();
|
| - return 0;
|
| +NamedProcessIterator::~NamedProcessIterator() {
|
| }
|
|
|
| -bool CleanupProcesses(const std::wstring& executable_name,
|
| - int wait_milliseconds,
|
| - int exit_code,
|
| - const ProcessFilter* filter) {
|
| +const ProcessEntry* NamedProcessIterator::NextProcessEntry() {
|
| + // Every call, you have to get new kinfo_procs_.
|
| + // Because the process status might be changed.
|
| + int num_of_kinfo_proc = 0;
|
| + index_of_kinfo_proc_ = 0;
|
| + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
|
| + size_t len = 0;
|
| +
|
| + if (sysctl(mib, arraysize(mib), NULL, &len, NULL, 0) < 0)
|
| + return NULL;
|
| +
|
| + num_of_kinfo_proc = len / sizeof(struct kinfo_proc);
|
| + // Leave some spare room for process table growth.
|
| + num_of_kinfo_proc += 16;
|
| + kinfo_procs_.resize(num_of_kinfo_proc);
|
| + len = num_of_kinfo_proc * sizeof(struct kinfo_proc);
|
| + if (sysctl(mib, arraysize(mib), &kinfo_procs_[0], &len, NULL, 0) < 0)
|
| + return NULL;
|
| +
|
| + num_of_kinfo_proc = len / sizeof(struct kinfo_proc);
|
| + kinfo_procs_.resize(num_of_kinfo_proc);
|
| +
|
| + bool result = false;
|
| + do {
|
| + result = CheckForNextProcess();
|
| + } while (result && !IncludeEntry());
|
| +
|
| + if (result)
|
| + return &entry_;
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| +bool NamedProcessIterator::CheckForNextProcess() {
|
| + std::string exec_name;
|
| + kinfo_proc* kinfo = NULL;
|
| + for (; index_of_kinfo_proc_ < kinfo_procs_.size(); ++index_of_kinfo_proc_) {
|
| + if (kinfo_procs_[index_of_kinfo_proc_].kp_proc.p_stat != SZOMB) {
|
| + kinfo = &kinfo_procs_[index_of_kinfo_proc_];
|
| +
|
| + int mib[] = { KERN_PROCARGS, KERN_PROCARGS, kinfo->kp_proc.p_pid };
|
| +
|
| + size_t data_len = 0;
|
| + if (sysctl(mib, arraysize(mib), NULL, &data_len, NULL, 0) < 0)
|
| + continue;
|
| +
|
| + std::string data;
|
| + data.resize(data_len); // Don't include the trailing NULL.
|
| + if (sysctl(mib, arraysize(mib), &data[0], &data_len, NULL, 0) < 0)
|
| + continue;
|
| +
|
| + // "data" has absolute process path with '/',
|
| + // so we get the last part as execution process name.
|
| +
|
| + int exec_name_end = data.find('\0');
|
| + int last_slash = data.rfind('/', exec_name_end);
|
| +
|
| + // If the index is not -1, it means valid exec name is found.
|
| + // Get the exec name and store the name into exec_name and break.
|
| + // "last_slash" point is '/', so get substr from the next.
|
| + if (last_slash != -1) {
|
| + exec_name = data.substr(exec_name_end - last_slash - 1);
|
| + } else {
|
| + exec_name = data.substr(0, exec_name_end);
|
| + }
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (index_of_kinfo_proc_ >= kinfo_procs_.size())
|
| + return false;
|
| +
|
| + entry_.pid = kinfo->kp_proc.p_pid;
|
| + entry_.ppid = kinfo->kp_proc.p_oppid;
|
| +
|
| + base::strlcpy(entry_.szExeFile, exec_name.c_str(), sizeof(entry_.szExeFile));
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool NamedProcessIterator::IncludeEntry() {
|
| + // TODO(port): make this also work for non-ASCII filenames
|
| + if (WideToUTF8(executable_name_) != entry_.szExeFile)
|
| + return false;
|
| + if (!filter_)
|
| + return true;
|
| + return filter_->Includes(entry_.pid, entry_.ppid);
|
| +}
|
| +
|
| +bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) {
|
| + // TODO(pinkerton): can we implement this? On linux it relies on /proc.
|
| NOTIMPLEMENTED();
|
| return false;
|
| }
|
|
|