summaryrefslogtreecommitdiffstats
path: root/chromium/base/process
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@digia.com>2014-03-18 13:16:26 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-03-20 15:55:39 +0100
commit3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch)
tree92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/base/process
parente90d7c4b152c56919d963987e2503f9909a666d2 (diff)
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies needed on Windows. Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42 Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu> Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/base/process')
-rw-r--r--chromium/base/process/internal_linux.h2
-rw-r--r--chromium/base/process/kill.h7
-rw-r--r--chromium/base/process/launch.cc1
-rw-r--r--chromium/base/process/launch.h31
-rw-r--r--chromium/base/process/launch_posix.cc4
-rw-r--r--chromium/base/process/launch_win.cc100
-rw-r--r--chromium/base/process/memory.h1
-rw-r--r--chromium/base/process/memory_linux.cc2
-rw-r--r--chromium/base/process/memory_mac.mm42
-rw-r--r--chromium/base/process/memory_unittest.cc13
-rw-r--r--chromium/base/process/process_handle_linux.cc2
-rw-r--r--chromium/base/process/process_metrics.cc8
-rw-r--r--chromium/base/process/process_metrics.h27
-rw-r--r--chromium/base/process/process_metrics_linux.cc203
-rw-r--r--chromium/base/process/process_metrics_unittest.cc397
-rw-r--r--chromium/base/process/process_metrics_unittest_ios.cc (renamed from chromium/base/process/process_util_unittest_ios.cc)7
-rw-r--r--chromium/base/process/process_metrics_unittests.cc63
-rw-r--r--chromium/base/process/process_util_unittest.cc216
18 files changed, 783 insertions, 343 deletions
diff --git a/chromium/base/process/internal_linux.h b/chromium/base/process/internal_linux.h
index a10cee36e56..0cacd3f3a84 100644
--- a/chromium/base/process/internal_linux.h
+++ b/chromium/base/process/internal_linux.h
@@ -8,6 +8,8 @@
#ifndef BASE_PROCESS_LINUX_INTERNAL_H_
#define BASE_PROCESS_LINUX_INTERNAL_H_
+#include <unistd.h>
+
#include "base/files/file_path.h"
namespace base {
diff --git a/chromium/base/process/kill.h b/chromium/base/process/kill.h
index c828c718def..de72d7a8dca 100644
--- a/chromium/base/process/kill.h
+++ b/chromium/base/process/kill.h
@@ -25,6 +25,13 @@ enum TerminationStatus {
TERMINATION_STATUS_PROCESS_WAS_KILLED, // e.g. SIGKILL or task manager kill
TERMINATION_STATUS_PROCESS_CRASHED, // e.g. Segmentation fault
TERMINATION_STATUS_STILL_RUNNING, // child hasn't exited yet
+#if defined(OS_ANDROID)
+ // On Android processes are spawned from the system Zygote and we do not get
+ // the termination status. We can't know if the termination was a crash or an
+ // oom kill for sure, but we can use status of the strong process bindings as
+ // a hint.
+ TERMINATION_STATUS_OOM_PROTECTED, // child was protected from oom kill
+#endif
TERMINATION_STATUS_MAX_ENUM
};
diff --git a/chromium/base/process/launch.cc b/chromium/base/process/launch.cc
index 1329a5af23e..0c9f3a88fef 100644
--- a/chromium/base/process/launch.cc
+++ b/chromium/base/process/launch.cc
@@ -10,6 +10,7 @@ LaunchOptions::LaunchOptions()
: wait(false),
#if defined(OS_WIN)
start_hidden(false),
+ handles_to_inherit(NULL),
inherit_handles(false),
as_user(NULL),
empty_desktop_name(false),
diff --git a/chromium/base/process/launch.h b/chromium/base/process/launch.h
index ac2df5eee5f..336bfba16e9 100644
--- a/chromium/base/process/launch.h
+++ b/chromium/base/process/launch.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 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.
@@ -16,17 +16,23 @@
#include "base/basictypes.h"
#include "base/environment.h"
#include "base/process/process_handle.h"
+#include "base/strings/string_piece.h"
#if defined(OS_POSIX)
#include "base/posix/file_descriptor_shuffle.h"
#elif defined(OS_WIN)
#include <windows.h>
+#include "base/win/scoped_handle.h"
#endif
class CommandLine;
namespace base {
+#if defined(OS_WIN)
+typedef std::vector<HANDLE> HandlesToInheritVector;
+#endif
+// TODO(viettrungluu): Only define this on POSIX?
typedef std::vector<std::pair<int, int> > FileHandleMappingVector;
// Options for launching a subprocess that are passed to LaunchProcess().
@@ -41,13 +47,19 @@ struct BASE_EXPORT LaunchOptions {
#if defined(OS_WIN)
bool start_hidden;
+ // If non-null, inherit exactly the list of handles in this vector (these
+ // handles must be inheritable). This is only supported on Vista and higher.
+ HandlesToInheritVector* handles_to_inherit;
+
// If true, the new process inherits handles from the parent. In production
// code this flag should be used only when running short-lived, trusted
// binaries, because open handles from other libraries and subsystems will
// leak to the child process, causing errors such as open socket hangs.
+ // Note: If |handles_to_inherit| is non-null, this flag is ignored and only
+ // those handles will be inherited (on Vista and higher).
bool inherit_handles;
- // If non-NULL, runs as if the user represented by the token had launched it.
+ // If non-null, runs as if the user represented by the token had launched it.
// Whether the application is visible on the interactive desktop depends on
// the token belonging to an interactive logon session.
//
@@ -59,7 +71,7 @@ struct BASE_EXPORT LaunchOptions {
// If true, use an empty string for the desktop name.
bool empty_desktop_name;
- // If non-NULL, launches the application in that job object. The process will
+ // If non-null, launches the application in that job object. The process will
// be terminated immediately and LaunchProcess() will fail if assignment to
// the job object fails.
HANDLE job_handle;
@@ -81,7 +93,7 @@ struct BASE_EXPORT LaunchOptions {
// the same environment. See AlterEnvironment().
EnvironmentMap environ;
- // If non-NULL, remap file descriptors according to the mapping of
+ // If non-null, remap file descriptors according to the mapping of
// src fd->dest fd to propagate FDs into the child process.
// This pointer is owned by the caller and must live through the
// call to LaunchProcess().
@@ -116,7 +128,7 @@ struct BASE_EXPORT LaunchOptions {
//
// Returns true upon success.
//
-// Upon success, if |process_handle| is non-NULL, it will be filled in with the
+// Upon success, if |process_handle| is non-null, it will be filled in with the
// handle of the launched process. NOTE: In this case, the caller is
// responsible for closing the handle so that it doesn't leak!
// Otherwise, the process handle will be implicitly closed.
@@ -146,7 +158,7 @@ BASE_EXPORT bool LaunchProcess(const CommandLine& cmdline,
// cmdline = "c:\windows\explorer.exe" -foo "c:\bar\"
BASE_EXPORT bool LaunchProcess(const string16& cmdline,
const LaunchOptions& options,
- ProcessHandle* process_handle);
+ win::ScopedHandle* process_handle);
#elif defined(OS_POSIX)
// A POSIX-specific version of LaunchProcess that takes an argv array
@@ -179,6 +191,13 @@ BASE_EXPORT void RouteStdioToConsole();
// indicating success).
BASE_EXPORT bool GetAppOutput(const CommandLine& cl, std::string* output);
+#if defined(OS_WIN)
+// A Windows-specific version of GetAppOutput that takes a command line string
+// instead of a CommandLine object. Useful for situations where you need to
+// control the command line arguments directly.
+BASE_EXPORT bool GetAppOutput(const StringPiece16& cl, std::string* output);
+#endif
+
#if defined(OS_POSIX)
// A POSIX-specific version of GetAppOutput that takes an argv array
// instead of a CommandLine. Useful for situations where you need to
diff --git a/chromium/base/process/launch_posix.cc b/chromium/base/process/launch_posix.cc
index de6286da26b..8dc8f9e215d 100644
--- a/chromium/base/process/launch_posix.cc
+++ b/chromium/base/process/launch_posix.cc
@@ -230,7 +230,7 @@ void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
// Since we're just trying to close anything we can find,
// ignore any error return values of close().
- ignore_result(HANDLE_EINTR(close(fd)));
+ close(fd);
}
return;
}
@@ -264,7 +264,7 @@ void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
// these FDs are >= |max_fds|, so we can check against that here
// before closing. See https://bugs.kde.org/show_bug.cgi?id=191758
if (fd < static_cast<int>(max_fds)) {
- int ret = HANDLE_EINTR(close(fd));
+ int ret = IGNORE_EINTR(close(fd));
DPCHECK(ret == 0);
}
}
diff --git a/chromium/base/process/launch_win.cc b/chromium/base/process/launch_win.cc
index da913efba74..0c831cf7b4a 100644
--- a/chromium/base/process/launch_win.cc
+++ b/chromium/base/process/launch_win.cc
@@ -11,6 +11,7 @@
#include <psapi.h>
#include <ios>
+#include <limits>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -25,6 +26,7 @@
#include "base/win/object_watcher.h"
#include "base/win/scoped_handle.h"
#include "base/win/scoped_process_information.h"
+#include "base/win/startup_information.h"
#include "base/win/windows_version.h"
// userenv.dll is required for CreateEnvironmentBlock().
@@ -103,27 +105,62 @@ void RouteStdioToConsole() {
bool LaunchProcess(const string16& cmdline,
const LaunchOptions& options,
- ProcessHandle* process_handle) {
- STARTUPINFO startup_info = {};
- startup_info.cb = sizeof(startup_info);
+ win::ScopedHandle* process_handle) {
+ win::StartupInformation startup_info_wrapper;
+ STARTUPINFO* startup_info = startup_info_wrapper.startup_info();
+
+ bool inherit_handles = options.inherit_handles;
+ DWORD flags = 0;
+ if (options.handles_to_inherit) {
+ if (options.handles_to_inherit->empty()) {
+ inherit_handles = false;
+ } else {
+ if (base::win::GetVersion() < base::win::VERSION_VISTA) {
+ DLOG(ERROR) << "Specifying handles to inherit requires Vista or later.";
+ return false;
+ }
+
+ if (options.handles_to_inherit->size() >
+ std::numeric_limits<DWORD>::max() / sizeof(HANDLE)) {
+ DLOG(ERROR) << "Too many handles to inherit.";
+ return false;
+ }
+
+ if (!startup_info_wrapper.InitializeProcThreadAttributeList(1)) {
+ DPLOG(ERROR);
+ return false;
+ }
+
+ if (!startup_info_wrapper.UpdateProcThreadAttribute(
+ PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
+ const_cast<HANDLE*>(&options.handles_to_inherit->at(0)),
+ static_cast<DWORD>(options.handles_to_inherit->size() *
+ sizeof(HANDLE)))) {
+ DPLOG(ERROR);
+ return false;
+ }
+
+ inherit_handles = true;
+ flags |= EXTENDED_STARTUPINFO_PRESENT;
+ }
+ }
+
if (options.empty_desktop_name)
- startup_info.lpDesktop = L"";
- startup_info.dwFlags = STARTF_USESHOWWINDOW;
- startup_info.wShowWindow = options.start_hidden ? SW_HIDE : SW_SHOW;
+ startup_info->lpDesktop = L"";
+ startup_info->dwFlags = STARTF_USESHOWWINDOW;
+ startup_info->wShowWindow = options.start_hidden ? SW_HIDE : SW_SHOW;
if (options.stdin_handle || options.stdout_handle || options.stderr_handle) {
- DCHECK(options.inherit_handles);
+ DCHECK(inherit_handles);
DCHECK(options.stdin_handle);
DCHECK(options.stdout_handle);
DCHECK(options.stderr_handle);
- startup_info.dwFlags |= STARTF_USESTDHANDLES;
- startup_info.hStdInput = options.stdin_handle;
- startup_info.hStdOutput = options.stdout_handle;
- startup_info.hStdError = options.stderr_handle;
+ startup_info->dwFlags |= STARTF_USESTDHANDLES;
+ startup_info->hStdInput = options.stdin_handle;
+ startup_info->hStdOutput = options.stdout_handle;
+ startup_info->hStdError = options.stderr_handle;
}
- DWORD flags = 0;
-
if (options.job_handle) {
flags |= CREATE_SUSPENDED;
@@ -136,7 +173,7 @@ bool LaunchProcess(const string16& cmdline,
if (options.force_breakaway_from_job_)
flags |= CREATE_BREAKAWAY_FROM_JOB;
- base::win::ScopedProcessInformation process_info;
+ PROCESS_INFORMATION temp_process_info = {};
if (options.as_user) {
flags |= CREATE_UNICODE_ENVIRONMENT;
@@ -150,9 +187,9 @@ bool LaunchProcess(const string16& cmdline,
BOOL launched =
CreateProcessAsUser(options.as_user, NULL,
const_cast<wchar_t*>(cmdline.c_str()),
- NULL, NULL, options.inherit_handles, flags,
- enviroment_block, NULL, &startup_info,
- process_info.Receive());
+ NULL, NULL, inherit_handles, flags,
+ enviroment_block, NULL, startup_info,
+ &temp_process_info);
DestroyEnvironmentBlock(enviroment_block);
if (!launched) {
DPLOG(ERROR);
@@ -161,12 +198,13 @@ bool LaunchProcess(const string16& cmdline,
} else {
if (!CreateProcess(NULL,
const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL,
- options.inherit_handles, flags, NULL, NULL,
- &startup_info, process_info.Receive())) {
+ inherit_handles, flags, NULL, NULL,
+ startup_info, &temp_process_info)) {
DPLOG(ERROR);
return false;
}
}
+ base::win::ScopedProcessInformation process_info(temp_process_info);
if (options.job_handle) {
if (0 == AssignProcessToJobObject(options.job_handle,
@@ -184,7 +222,7 @@ bool LaunchProcess(const string16& cmdline,
// If the caller wants the process handle, we won't close it.
if (process_handle)
- *process_handle = process_info.TakeProcessHandle();
+ process_handle->Set(process_info.TakeProcessHandle());
return true;
}
@@ -192,7 +230,13 @@ bool LaunchProcess(const string16& cmdline,
bool LaunchProcess(const CommandLine& cmdline,
const LaunchOptions& options,
ProcessHandle* process_handle) {
- return LaunchProcess(cmdline.GetCommandLineString(), options, process_handle);
+ if (!process_handle)
+ return LaunchProcess(cmdline.GetCommandLineString(), options, NULL);
+
+ win::ScopedHandle process;
+ bool rv = LaunchProcess(cmdline.GetCommandLineString(), options, &process);
+ *process_handle = process.Take();
+ return rv;
}
bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags) {
@@ -206,6 +250,10 @@ bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags) {
}
bool GetAppOutput(const CommandLine& cl, std::string* output) {
+ return GetAppOutput(cl.GetCommandLineString(), output);
+}
+
+bool GetAppOutput(const StringPiece16& cl, std::string* output) {
HANDLE out_read = NULL;
HANDLE out_write = NULL;
@@ -231,10 +279,10 @@ bool GetAppOutput(const CommandLine& cl, std::string* output) {
return false;
}
- FilePath::StringType writable_command_line_string(cl.GetCommandLineString());
+ FilePath::StringType writable_command_line_string;
+ writable_command_line_string.assign(cl.data(), cl.size());
- base::win::ScopedProcessInformation proc_info;
- STARTUPINFO start_info = { 0 };
+ STARTUPINFO start_info = {};
start_info.cb = sizeof(STARTUPINFO);
start_info.hStdOutput = out_write;
@@ -244,14 +292,16 @@ bool GetAppOutput(const CommandLine& cl, std::string* output) {
start_info.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
+ PROCESS_INFORMATION temp_process_info = {};
if (!CreateProcess(NULL,
&writable_command_line_string[0],
NULL, NULL,
TRUE, // Handles are inherited.
- 0, NULL, NULL, &start_info, proc_info.Receive())) {
+ 0, NULL, NULL, &start_info, &temp_process_info)) {
NOTREACHED() << "Failed to start process";
return false;
}
+ base::win::ScopedProcessInformation proc_info(temp_process_info);
// Close our writing end of pipe now. Otherwise later read would not be able
// to detect end of child's output.
diff --git a/chromium/base/process/memory.h b/chromium/base/process/memory.h
index de79477e95d..e6696cb8a70 100644
--- a/chromium/base/process/memory.h
+++ b/chromium/base/process/memory.h
@@ -62,6 +62,7 @@ BASE_EXPORT bool AdjustOOMScore(ProcessId process, int score);
// IF YOU USE THIS WITHOUT CONSULTING YOUR FRIENDLY OSX DEVELOPER,
// YOUR CODE IS LIKELY TO BE REVERTED. THANK YOU.
BASE_EXPORT void* UncheckedMalloc(size_t size);
+BASE_EXPORT void* UncheckedCalloc(size_t num_items, size_t size);
#endif // defined(OS_MACOSX)
} // namespace base
diff --git a/chromium/base/process/memory_linux.cc b/chromium/base/process/memory_linux.cc
index f81429b2ac0..6bed68bd832 100644
--- a/chromium/base/process/memory_linux.cc
+++ b/chromium/base/process/memory_linux.cc
@@ -18,6 +18,7 @@ size_t g_oom_size = 0U;
namespace {
+#if !defined(OS_ANDROID)
void OnNoMemorySize(size_t size) {
g_oom_size = size;
@@ -29,6 +30,7 @@ void OnNoMemorySize(size_t size) {
void OnNoMemory() {
OnNoMemorySize(0);
}
+#endif // !defined(OS_ANDROID)
} // namespace
diff --git a/chromium/base/process/memory_mac.mm b/chromium/base/process/memory_mac.mm
index dd30e704c8f..3e281cd8e3c 100644
--- a/chromium/base/process/memory_mac.mm
+++ b/chromium/base/process/memory_mac.mm
@@ -108,7 +108,7 @@ class ThreadLocalBooleanAutoReset {
};
base::LazyInstance<ThreadLocalBoolean>::Leaky
- g_unchecked_malloc = LAZY_INSTANCE_INITIALIZER;
+ g_unchecked_alloc = LAZY_INSTANCE_INITIALIZER;
// NOTE(shess): This is called when the malloc library noticed that the heap
// is fubar. Avoid calls which will re-enter the malloc library.
@@ -117,10 +117,23 @@ void CrMallocErrorBreak() {
// Out of memory is certainly not heap corruption, and not necessarily
// something for which the process should be terminated. Leave that decision
- // to the OOM killer. The EBADF case comes up because the malloc library
- // attempts to log to ASL (syslog) before calling this code, which fails
- // accessing a Unix-domain socket because of sandboxing.
- if (errno == ENOMEM || (errno == EBADF && g_unchecked_malloc.Get().Get()))
+ // to the OOM killer.
+ if (errno == ENOMEM)
+ return;
+
+ // The malloc library attempts to log to ASL (syslog) before calling this
+ // code, which fails accessing a Unix-domain socket when sandboxed. The
+ // failed socket results in writing to a -1 fd, leaving EBADF in errno. If
+ // UncheckedMalloc() is on the stack, for large allocations (15k and up) only
+ // an OOM failure leads here. Smaller allocations could also arrive here due
+ // to freelist corruption, but there is no way to distinguish that from OOM at
+ // this point.
+ //
+ // NOTE(shess): I hypothesize that EPERM case in 10.9 is the same root cause
+ // as EBADF. Unfortunately, 10.9's opensource releases don't include malloc
+ // source code at this time.
+ // <http://crbug.com/312234>
+ if ((errno == EBADF || errno == EPERM) && g_unchecked_alloc.Get().Get())
return;
// A unit test checks this error message, so it needs to be in release builds.
@@ -422,7 +435,7 @@ void oom_killer_new() {
// === Core Foundation CFAllocators ===
bool CanGetContextForCFAllocator() {
- return !base::mac::IsOSLaterThanMountainLion_DontCallThis();
+ return !base::mac::IsOSLaterThanMavericks_DontCallThis();
}
CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) {
@@ -431,7 +444,9 @@ CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) {
const_cast<ChromeCFAllocatorLeopards*>(
reinterpret_cast<const ChromeCFAllocatorLeopards*>(allocator));
return &our_allocator->_context;
- } else if (base::mac::IsOSLion() || base::mac::IsOSMountainLion()) {
+ } else if (base::mac::IsOSLion() ||
+ base::mac::IsOSMountainLion() ||
+ base::mac::IsOSMavericks()) {
ChromeCFAllocatorLions* our_allocator =
const_cast<ChromeCFAllocatorLions*>(
reinterpret_cast<const ChromeCFAllocatorLions*>(allocator));
@@ -491,13 +506,24 @@ void* UncheckedMalloc(size_t size) {
if (g_old_malloc) {
#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
- ThreadLocalBooleanAutoReset flag(g_unchecked_malloc.Pointer(), true);
+ ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true);
#endif // ARCH_CPU_32_BITS
return g_old_malloc(malloc_default_zone(), size);
}
return malloc(size);
}
+void* UncheckedCalloc(size_t num_items, size_t size) {
+ if (g_old_calloc) {
+#if ARCH_CPU_32_BITS
+ ScopedClearErrno clear_errno;
+ ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true);
+#endif // ARCH_CPU_32_BITS
+ return g_old_calloc(malloc_default_zone(), num_items, size);
+ }
+ return calloc(num_items, size);
+}
+
void EnableTerminationOnOutOfMemory() {
if (g_oom_killer_enabled)
return;
diff --git a/chromium/base/process/memory_unittest.cc b/chromium/base/process/memory_unittest.cc
index a1f30526aa3..e5c759d5711 100644
--- a/chromium/base/process/memory_unittest.cc
+++ b/chromium/base/process/memory_unittest.cc
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/debug/alias.h"
+#include "base/strings/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_WIN)
@@ -23,7 +24,6 @@
#include "base/process/memory_unittest_mac.h"
#endif
#if defined(OS_LINUX)
-#include <glib.h>
#include <malloc.h>
#endif
@@ -260,14 +260,13 @@ TEST_F(OutOfMemoryDeathTest, Memalign) {
}
TEST_F(OutOfMemoryDeathTest, ViaSharedLibraries) {
- // g_try_malloc is documented to return NULL on failure. (g_malloc is the
- // 'safe' default that crashes if allocation fails). However, since we have
- // hopefully overridden malloc, even g_try_malloc should fail. This tests
- // that the run-time symbol resolution is overriding malloc for shared
- // libraries as well as for our code.
+ // This tests that the run-time symbol resolution is overriding malloc for
+ // shared libraries (including libc itself) as well as for our code.
+ std::string format = base::StringPrintf("%%%zud", test_size_);
+ char *value = NULL;
ASSERT_DEATH({
SetUpInDeathAssert();
- value_ = g_try_malloc(test_size_);
+ EXPECT_EQ(-1, asprintf(&value, format.c_str(), 0));
}, "");
}
#endif // OS_LINUX
diff --git a/chromium/base/process/process_handle_linux.cc b/chromium/base/process/process_handle_linux.cc
index 91441f7b38c..0f7ccd348a8 100644
--- a/chromium/base/process/process_handle_linux.cc
+++ b/chromium/base/process/process_handle_linux.cc
@@ -20,7 +20,7 @@ ProcessId GetParentProcessId(ProcessHandle process) {
FilePath GetProcessExecutablePath(ProcessHandle process) {
FilePath stat_file = internal::GetProcPidDir(process).Append("exe");
FilePath exe_name;
- if (!file_util::ReadSymbolicLink(stat_file, &exe_name)) {
+ if (!ReadSymbolicLink(stat_file, &exe_name)) {
// No such process. Happens frequently in e.g. TerminateAllChromeProcesses
return FilePath();
}
diff --git a/chromium/base/process/process_metrics.cc b/chromium/base/process/process_metrics.cc
index 127fb4649f7..83289b8c78b 100644
--- a/chromium/base/process/process_metrics.cc
+++ b/chromium/base/process/process_metrics.cc
@@ -42,4 +42,12 @@ scoped_ptr<Value> SystemMetrics::ToValue() const {
return res.PassAs<Value>();
}
+double ProcessMetrics::GetPlatformIndependentCPUUsage() {
+#if defined(OS_WIN)
+ return GetCPUUsage() * processor_count_;
+#else
+ return GetCPUUsage();
+#endif
+}
+
} // namespace base
diff --git a/chromium/base/process/process_metrics.h b/chromium/base/process/process_metrics.h
index f6b225fa94f..560490a9b8c 100644
--- a/chromium/base/process/process_metrics.h
+++ b/chromium/base/process/process_metrics.h
@@ -160,14 +160,19 @@ class BASE_EXPORT ProcessMetrics {
// load and fragmentation.
bool CalculateFreeMemory(FreeMBytes* free) const;
- // Returns the CPU usage in percent since the last time this method was
- // called. The first time this method is called it returns 0 and will return
- // the actual CPU info on subsequent calls.
- // On Windows, the CPU usage value is for all CPUs. So if you have 2 CPUs and
- // your process is using all the cycles of 1 CPU and not the other CPU, this
- // method returns 50.
+ // Returns the CPU usage in percent since the last time this method or
+ // GetPlatformIndependentCPUUsage() was called. The first time this method
+ // is called it returns 0 and will return the actual CPU info on subsequent
+ // calls. On Windows, the CPU usage value is for all CPUs. So if you have
+ // 2 CPUs and your process is using all the cycles of 1 CPU and not the other
+ // CPU, this method returns 50.
double GetCPUUsage();
+ // Same as GetCPUUsage(), but will return consistent values on all platforms
+ // (cancelling the Windows exception mentioned above) by returning a value in
+ // the range of 0 to (100 * numCPUCores) everywhere.
+ double GetPlatformIndependentCPUUsage();
+
// Retrieves accounting information for all I/O operations performed by the
// process.
// If IO information is retrieved successfully, the function returns true
@@ -273,6 +278,16 @@ struct BASE_EXPORT SystemMemoryInfoKB {
#endif
};
+// Parses a string containing the contents of /proc/meminfo
+// returns true on success or false for a parsing error
+BASE_EXPORT bool ParseProcMeminfo(const std::string& input,
+ SystemMemoryInfoKB* meminfo);
+
+// Parses a string containing the contents of /proc/vmstat
+// returns true on success or false for a parsing error
+BASE_EXPORT bool ParseProcVmstat(const std::string& input,
+ SystemMemoryInfoKB* meminfo);
+
// Retrieves data from /proc/meminfo and /proc/vmstat
// about system-wide memory consumption.
// Fills in the provided |meminfo| structure. Returns true on success.
diff --git a/chromium/base/process/process_metrics_linux.cc b/chromium/base/process/process_metrics_linux.cc
index 7f46639e4a4..afa88486a0b 100644
--- a/chromium/base/process/process_metrics_linux.cc
+++ b/chromium/base/process/process_metrics_linux.cc
@@ -405,33 +405,6 @@ int GetNumberOfThreads(ProcessHandle process) {
namespace {
-// The format of /proc/meminfo is:
-//
-// MemTotal: 8235324 kB
-// MemFree: 1628304 kB
-// Buffers: 429596 kB
-// Cached: 4728232 kB
-// ...
-const size_t kMemTotalIndex = 1;
-const size_t kMemFreeIndex = 4;
-const size_t kMemBuffersIndex = 7;
-const size_t kMemCachedIndex = 10;
-const size_t kMemActiveAnonIndex = 22;
-const size_t kMemInactiveAnonIndex = 25;
-const size_t kMemActiveFileIndex = 28;
-const size_t kMemInactiveFileIndex = 31;
-
-// The format of /proc/vmstat is:
-//
-// nr_free_pages 299878
-// nr_inactive_anon 239863
-// nr_active_anon 1318966
-// nr_inactive_file 2015629
-// ...
-const size_t kVMPagesSwappedIn = 75;
-const size_t kVMPagesSwappedOut = 77;
-const size_t kVMPageMajorFaults = 95;
-
// The format of /proc/diskstats is:
// Device major number
// Device minor number
@@ -538,6 +511,123 @@ scoped_ptr<Value> SystemMemoryInfoKB::ToValue() const {
return res.PassAs<Value>();
}
+// exposed for testing
+bool ParseProcMeminfo(const std::string& meminfo_data,
+ SystemMemoryInfoKB* meminfo) {
+ // The format of /proc/meminfo is:
+ //
+ // MemTotal: 8235324 kB
+ // MemFree: 1628304 kB
+ // Buffers: 429596 kB
+ // Cached: 4728232 kB
+ // ...
+ // There is no guarantee on the ordering or position
+ // though it doesn't appear to change very often
+
+ // As a basic sanity check, let's make sure we at least get non-zero
+ // MemTotal value
+ meminfo->total = 0;
+
+ std::vector<std::string> meminfo_lines;
+ Tokenize(meminfo_data, "\n", &meminfo_lines);
+ for (std::vector<std::string>::iterator it = meminfo_lines.begin();
+ it != meminfo_lines.end(); ++it) {
+ std::vector<std::string> tokens;
+ SplitStringAlongWhitespace(*it, &tokens);
+ // HugePages_* only has a number and no suffix so we can't rely on
+ // there being exactly 3 tokens.
+ if (tokens.size() > 1) {
+ if (tokens[0] == "MemTotal:") {
+ StringToInt(tokens[1], &meminfo->total);
+ continue;
+ } if (tokens[0] == "MemFree:") {
+ StringToInt(tokens[1], &meminfo->free);
+ continue;
+ } if (tokens[0] == "Buffers:") {
+ StringToInt(tokens[1], &meminfo->buffers);
+ continue;
+ } if (tokens[0] == "Cached:") {
+ StringToInt(tokens[1], &meminfo->cached);
+ continue;
+ } if (tokens[0] == "Active(anon):") {
+ StringToInt(tokens[1], &meminfo->active_anon);
+ continue;
+ } if (tokens[0] == "Inactive(anon):") {
+ StringToInt(tokens[1], &meminfo->inactive_anon);
+ continue;
+ } if (tokens[0] == "Active(file):") {
+ StringToInt(tokens[1], &meminfo->active_file);
+ continue;
+ } if (tokens[0] == "Inactive(file):") {
+ StringToInt(tokens[1], &meminfo->inactive_file);
+ continue;
+ } if (tokens[0] == "SwapTotal:") {
+ StringToInt(tokens[1], &meminfo->swap_total);
+ continue;
+ } if (tokens[0] == "SwapFree:") {
+ StringToInt(tokens[1], &meminfo->swap_free);
+ continue;
+ } if (tokens[0] == "Dirty:") {
+ StringToInt(tokens[1], &meminfo->dirty);
+ continue;
+#if defined(OS_CHROMEOS)
+ // Chrome OS has a tweaked kernel that allows us to query Shmem, which is
+ // usually video memory otherwise invisible to the OS.
+ } if (tokens[0] == "Shmem:") {
+ StringToInt(tokens[1], &meminfo->shmem);
+ continue;
+ } if (tokens[0] == "Slab:") {
+ StringToInt(tokens[1], &meminfo->slab);
+ continue;
+#endif
+ }
+ } else
+ DLOG(WARNING) << "meminfo: tokens: " << tokens.size()
+ << " malformed line: " << *it;
+ }
+
+ // Make sure we got a valid MemTotal.
+ if (!meminfo->total)
+ return false;
+
+ return true;
+}
+
+// exposed for testing
+bool ParseProcVmstat(const std::string& vmstat_data,
+ SystemMemoryInfoKB* meminfo) {
+ // The format of /proc/vmstat is:
+ //
+ // nr_free_pages 299878
+ // nr_inactive_anon 239863
+ // nr_active_anon 1318966
+ // nr_inactive_file 2015629
+ // ...
+ //
+ // We iterate through the whole file because the position of the
+ // fields are dependent on the kernel version and configuration.
+
+ std::vector<std::string> vmstat_lines;
+ Tokenize(vmstat_data, "\n", &vmstat_lines);
+ for (std::vector<std::string>::iterator it = vmstat_lines.begin();
+ it != vmstat_lines.end(); ++it) {
+ std::vector<std::string> tokens;
+ SplitString(*it, ' ', &tokens);
+ if (tokens.size() == 2) {
+ if (tokens[0] == "pswpin") {
+ StringToInt(tokens[1], &meminfo->pswpin);
+ continue;
+ } if (tokens[0] == "pswpout") {
+ StringToInt(tokens[1], &meminfo->pswpout);
+ continue;
+ } if (tokens[0] == "pgmajfault")
+ StringToInt(tokens[1], &meminfo->pgmajfault);
+ }
+ }
+
+ return true;
+}
+
bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
// Synchronously reading files in /proc is safe.
ThreadRestrictions::ScopedAllowIO allow_io;
@@ -549,55 +639,13 @@ bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
DLOG(WARNING) << "Failed to open " << meminfo_file.value();
return false;
}
- std::vector<std::string> meminfo_fields;
- SplitStringAlongWhitespace(meminfo_data, &meminfo_fields);
- if (meminfo_fields.size() < kMemCachedIndex) {
- DLOG(WARNING) << "Failed to parse " << meminfo_file.value()
- << ". Only found " << meminfo_fields.size() << " fields.";
+ if (!ParseProcMeminfo(meminfo_data, meminfo)) {
+ DLOG(WARNING) << "Failed to parse " << meminfo_file.value();
return false;
}
- DCHECK_EQ(meminfo_fields[kMemTotalIndex-1], "MemTotal:");
- DCHECK_EQ(meminfo_fields[kMemFreeIndex-1], "MemFree:");
- DCHECK_EQ(meminfo_fields[kMemBuffersIndex-1], "Buffers:");
- DCHECK_EQ(meminfo_fields[kMemCachedIndex-1], "Cached:");
- DCHECK_EQ(meminfo_fields[kMemActiveAnonIndex-1], "Active(anon):");
- DCHECK_EQ(meminfo_fields[kMemInactiveAnonIndex-1], "Inactive(anon):");
- DCHECK_EQ(meminfo_fields[kMemActiveFileIndex-1], "Active(file):");
- DCHECK_EQ(meminfo_fields[kMemInactiveFileIndex-1], "Inactive(file):");
-
- StringToInt(meminfo_fields[kMemTotalIndex], &meminfo->total);
- StringToInt(meminfo_fields[kMemFreeIndex], &meminfo->free);
- StringToInt(meminfo_fields[kMemBuffersIndex], &meminfo->buffers);
- StringToInt(meminfo_fields[kMemCachedIndex], &meminfo->cached);
- StringToInt(meminfo_fields[kMemActiveAnonIndex], &meminfo->active_anon);
- StringToInt(meminfo_fields[kMemInactiveAnonIndex], &meminfo->inactive_anon);
- StringToInt(meminfo_fields[kMemActiveFileIndex], &meminfo->active_file);
- StringToInt(meminfo_fields[kMemInactiveFileIndex], &meminfo->inactive_file);
-
- // We don't know when these fields appear, so we must search for them.
- for (size_t i = kMemCachedIndex+2; i < meminfo_fields.size(); i += 3) {
- if (meminfo_fields[i] == "SwapTotal:")
- StringToInt(meminfo_fields[i+1], &meminfo->swap_total);
- if (meminfo_fields[i] == "SwapFree:")
- StringToInt(meminfo_fields[i+1], &meminfo->swap_free);
- if (meminfo_fields[i] == "Dirty:")
- StringToInt(meminfo_fields[i+1], &meminfo->dirty);
- }
-
#if defined(OS_CHROMEOS)
- // Chrome OS has a tweaked kernel that allows us to query Shmem, which is
- // usually video memory otherwise invisible to the OS. Unfortunately, the
- // meminfo format varies on different hardware so we have to search for the
- // string. It always appears after "Cached:".
- for (size_t i = kMemCachedIndex+2; i < meminfo_fields.size(); i += 3) {
- if (meminfo_fields[i] == "Shmem:")
- StringToInt(meminfo_fields[i+1], &meminfo->shmem);
- if (meminfo_fields[i] == "Slab:")
- StringToInt(meminfo_fields[i+1], &meminfo->slab);
- }
-
// Report on Chrome OS GEM object graphics memory. /var/run/debugfs_gpu is a
// bind mount into /sys/kernel/debug and synchronously reading the in-memory
// files in /sys is fast.
@@ -640,15 +688,10 @@ bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
DLOG(WARNING) << "Failed to open " << vmstat_file.value();
return false;
}
-
- std::vector<std::string> vmstat_fields;
- SplitStringAlongWhitespace(vmstat_data, &vmstat_fields);
- if (vmstat_fields[kVMPagesSwappedIn-1] == "pswpin")
- StringToInt(vmstat_fields[kVMPagesSwappedIn], &meminfo->pswpin);
- if (vmstat_fields[kVMPagesSwappedOut-1] == "pswpout")
- StringToInt(vmstat_fields[kVMPagesSwappedOut], &meminfo->pswpout);
- if (vmstat_fields[kVMPageMajorFaults-1] == "pgmajfault")
- StringToInt(vmstat_fields[kVMPageMajorFaults], &meminfo->pgmajfault);
+ if (!ParseProcVmstat(vmstat_data, meminfo)) {
+ DLOG(WARNING) << "Failed to parse " << vmstat_file.value();
+ return false;
+ }
return true;
}
diff --git a/chromium/base/process/process_metrics_unittest.cc b/chromium/base/process/process_metrics_unittest.cc
new file mode 100644
index 00000000000..5d365d9a203
--- /dev/null
+++ b/chromium/base/process/process_metrics_unittest.cc
@@ -0,0 +1,397 @@
+// Copyright 2013 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 "base/process/process_metrics.h"
+
+#include <sstream>
+#include <string>
+
+#include "base/threading/thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+
+namespace base {
+namespace debug {
+
+// Tests for SystemMetrics.
+// Exists as a class so it can be a friend of SystemMetrics.
+class SystemMetricsTest : public testing::Test {
+ public:
+ SystemMetricsTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SystemMetricsTest);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+TEST_F(SystemMetricsTest, IsValidDiskName) {
+ std::string invalid_input1 = "";
+ std::string invalid_input2 = "s";
+ std::string invalid_input3 = "sdz+";
+ std::string invalid_input4 = "hda0";
+ std::string invalid_input5 = "mmcbl";
+ std::string invalid_input6 = "mmcblka";
+ std::string invalid_input7 = "mmcblkb";
+ std::string invalid_input8 = "mmmblk0";
+
+ EXPECT_FALSE(IsValidDiskName(invalid_input1));
+ EXPECT_FALSE(IsValidDiskName(invalid_input2));
+ EXPECT_FALSE(IsValidDiskName(invalid_input3));
+ EXPECT_FALSE(IsValidDiskName(invalid_input4));
+ EXPECT_FALSE(IsValidDiskName(invalid_input5));
+ EXPECT_FALSE(IsValidDiskName(invalid_input6));
+ EXPECT_FALSE(IsValidDiskName(invalid_input7));
+ EXPECT_FALSE(IsValidDiskName(invalid_input8));
+
+ std::string valid_input1 = "sda";
+ std::string valid_input2 = "sdaaaa";
+ std::string valid_input3 = "hdz";
+ std::string valid_input4 = "mmcblk0";
+ std::string valid_input5 = "mmcblk999";
+
+ EXPECT_TRUE(IsValidDiskName(valid_input1));
+ EXPECT_TRUE(IsValidDiskName(valid_input2));
+ EXPECT_TRUE(IsValidDiskName(valid_input3));
+ EXPECT_TRUE(IsValidDiskName(valid_input4));
+ EXPECT_TRUE(IsValidDiskName(valid_input5));
+}
+
+TEST_F(SystemMetricsTest, ParseMeminfo) {
+ struct SystemMemoryInfoKB meminfo;
+ std::string invalid_input1 = "abc";
+ std::string invalid_input2 = "MemTotal:";
+ // Partial file with no MemTotal
+ std::string invalid_input3 =
+ "MemFree: 3913968 kB\n"
+ "Buffers: 2348340 kB\n"
+ "Cached: 49071596 kB\n"
+ "SwapCached: 12 kB\n"
+ "Active: 36393900 kB\n"
+ "Inactive: 21221496 kB\n"
+ "Active(anon): 5674352 kB\n"
+ "Inactive(anon): 633992 kB\n";
+ EXPECT_FALSE(ParseProcMeminfo(invalid_input1, &meminfo));
+ EXPECT_FALSE(ParseProcMeminfo(invalid_input2, &meminfo));
+ EXPECT_FALSE(ParseProcMeminfo(invalid_input3, &meminfo));
+
+ std::string valid_input1 =
+ "MemTotal: 3981504 kB\n"
+ "MemFree: 140764 kB\n"
+ "Buffers: 116480 kB\n"
+ "Cached: 406160 kB\n"
+ "SwapCached: 21304 kB\n"
+ "Active: 3152040 kB\n"
+ "Inactive: 472856 kB\n"
+ "Active(anon): 2972352 kB\n"
+ "Inactive(anon): 270108 kB\n"
+ "Active(file): 179688 kB\n"
+ "Inactive(file): 202748 kB\n"
+ "Unevictable: 0 kB\n"
+ "Mlocked: 0 kB\n"
+ "SwapTotal: 5832280 kB\n"
+ "SwapFree: 3672368 kB\n"
+ "Dirty: 184 kB\n"
+ "Writeback: 0 kB\n"
+ "AnonPages: 3101224 kB\n"
+ "Mapped: 142296 kB\n"
+ "Shmem: 140204 kB\n"
+ "Slab: 54212 kB\n"
+ "SReclaimable: 30936 kB\n"
+ "SUnreclaim: 23276 kB\n"
+ "KernelStack: 2464 kB\n"
+ "PageTables: 24812 kB\n"
+ "NFS_Unstable: 0 kB\n"
+ "Bounce: 0 kB\n"
+ "WritebackTmp: 0 kB\n"
+ "CommitLimit: 7823032 kB\n"
+ "Committed_AS: 7973536 kB\n"
+ "VmallocTotal: 34359738367 kB\n"
+ "VmallocUsed: 375940 kB\n"
+ "VmallocChunk: 34359361127 kB\n"
+ "DirectMap4k: 72448 kB\n"
+ "DirectMap2M: 4061184 kB\n";
+ // output from a much older kernel where the Active and Inactive aren't
+ // broken down into anon and file and Huge Pages are enabled
+ std::string valid_input2 =
+ "MemTotal: 255908 kB\n"
+ "MemFree: 69936 kB\n"
+ "Buffers: 15812 kB\n"
+ "Cached: 115124 kB\n"
+ "SwapCached: 0 kB\n"
+ "Active: 92700 kB\n"
+ "Inactive: 63792 kB\n"
+ "HighTotal: 0 kB\n"
+ "HighFree: 0 kB\n"
+ "LowTotal: 255908 kB\n"
+ "LowFree: 69936 kB\n"
+ "SwapTotal: 524280 kB\n"
+ "SwapFree: 524200 kB\n"
+ "Dirty: 4 kB\n"
+ "Writeback: 0 kB\n"
+ "Mapped: 42236 kB\n"
+ "Slab: 25912 kB\n"
+ "Committed_AS: 118680 kB\n"
+ "PageTables: 1236 kB\n"
+ "VmallocTotal: 3874808 kB\n"
+ "VmallocUsed: 1416 kB\n"
+ "VmallocChunk: 3872908 kB\n"
+ "HugePages_Total: 0\n"
+ "HugePages_Free: 0\n"
+ "Hugepagesize: 4096 kB\n";
+
+ EXPECT_TRUE(ParseProcMeminfo(valid_input1, &meminfo));
+ EXPECT_TRUE(meminfo.total == 3981504);
+ EXPECT_TRUE(meminfo.free == 140764);
+ EXPECT_TRUE(meminfo.buffers == 116480);
+ EXPECT_TRUE(meminfo.cached == 406160);
+ EXPECT_TRUE(meminfo.active_anon == 2972352);
+ EXPECT_TRUE(meminfo.active_file == 179688);
+ EXPECT_TRUE(meminfo.inactive_anon == 270108);
+ EXPECT_TRUE(meminfo.inactive_file == 202748);
+ EXPECT_TRUE(meminfo.swap_total == 5832280);
+ EXPECT_TRUE(meminfo.swap_free == 3672368);
+ EXPECT_TRUE(meminfo.dirty == 184);
+#if defined(OS_CHROMEOS)
+ EXPECT_TRUE(meminfo.shmem == 140204);
+ EXPECT_TRUE(meminfo.slab == 54212);
+#endif
+ EXPECT_TRUE(ParseProcMeminfo(valid_input2, &meminfo));
+ EXPECT_TRUE(meminfo.total == 255908);
+ EXPECT_TRUE(meminfo.free == 69936);
+ EXPECT_TRUE(meminfo.buffers == 15812);
+ EXPECT_TRUE(meminfo.cached == 115124);
+ EXPECT_TRUE(meminfo.swap_total == 524280);
+ EXPECT_TRUE(meminfo.swap_free == 524200);
+ EXPECT_TRUE(meminfo.dirty == 4);
+}
+
+TEST_F(SystemMetricsTest, ParseVmstat) {
+ struct SystemMemoryInfoKB meminfo;
+ // part of vmstat from a 3.2 kernel with numa enabled
+ std::string valid_input1 =
+ "nr_free_pages 905104\n"
+ "nr_inactive_anon 142478"
+ "nr_active_anon 1520046\n"
+ "nr_inactive_file 4481001\n"
+ "nr_active_file 8313439\n"
+ "nr_unevictable 5044\n"
+ "nr_mlock 5044\n"
+ "nr_anon_pages 1633780\n"
+ "nr_mapped 104742\n"
+ "nr_file_pages 12828218\n"
+ "nr_dirty 245\n"
+ "nr_writeback 0\n"
+ "nr_slab_reclaimable 831609\n"
+ "nr_slab_unreclaimable 41164\n"
+ "nr_page_table_pages 31470\n"
+ "nr_kernel_stack 1735\n"
+ "nr_unstable 0\n"
+ "nr_bounce 0\n"
+ "nr_vmscan_write 406\n"
+ "nr_vmscan_immediate_reclaim 281\n"
+ "nr_writeback_temp 0\n"
+ "nr_isolated_anon 0\n"
+ "nr_isolated_file 0\n"
+ "nr_shmem 28820\n"
+ "nr_dirtied 84674644\n"
+ "nr_written 75307109\n"
+ "nr_anon_transparent_hugepages 0\n"
+ "nr_dirty_threshold 1536206\n"
+ "nr_dirty_background_threshold 768103\n"
+ "pgpgin 30777108\n"
+ "pgpgout 319023278\n"
+ "pswpin 179\n"
+ "pswpout 406\n"
+ "pgalloc_dma 0\n"
+ "pgalloc_dma32 20833399\n"
+ "pgalloc_normal 1622609290\n"
+ "pgalloc_movable 0\n"
+ "pgfree 1644355583\n"
+ "pgactivate 75391882\n"
+ "pgdeactivate 4121019\n"
+ "pgfault 2542879679\n"
+ "pgmajfault 487192\n";
+ std::string valid_input2 =
+ "nr_free_pages 180125\n"
+ "nr_inactive_anon 51\n"
+ "nr_active_anon 38832\n"
+ "nr_inactive_file 50171\n"
+ "nr_active_file 47510\n"
+ "nr_unevictable 0\n"
+ "nr_mlock 0\n"
+ "nr_anon_pages 38825\n"
+ "nr_mapped 24043\n"
+ "nr_file_pages 97733\n"
+ "nr_dirty 0\n"
+ "nr_writeback 0\n"
+ "nr_slab_reclaimable 4032\n"
+ "nr_slab_unreclaimable 2848\n"
+ "nr_page_table_pages 1505\n"
+ "nr_kernel_stack 626\n"
+ "nr_unstable 0\n"
+ "nr_bounce 0\n"
+ "nr_vmscan_write 0\n"
+ "nr_vmscan_immediate_reclaim 0\n"
+ "nr_writeback_temp 0\n"
+ "nr_isolated_anon 0\n"
+ "nr_isolated_file 0\n"
+ "nr_shmem 58\n"
+ "nr_dirtied 435358\n"
+ "nr_written 401258\n"
+ "nr_anon_transparent_hugepages 0\n"
+ "nr_dirty_threshold 18566\n"
+ "nr_dirty_background_threshold 4641\n"
+ "pgpgin 299464\n"
+ "pgpgout 2437788\n"
+ "pswpin 12\n"
+ "pswpout 901\n"
+ "pgalloc_normal 144213030\n"
+ "pgalloc_high 164501274\n"
+ "pgalloc_movable 0\n"
+ "pgfree 308894908\n"
+ "pgactivate 239320\n"
+ "pgdeactivate 1\n"
+ "pgfault 716044601\n"
+ "pgmajfault 2023\n"
+ "pgrefill_normal 0\n"
+ "pgrefill_high 0\n"
+ "pgrefill_movable 0\n";
+ EXPECT_TRUE(ParseProcVmstat(valid_input1, &meminfo));
+ EXPECT_TRUE(meminfo.pswpin == 179);
+ EXPECT_TRUE(meminfo.pswpout == 406);
+ EXPECT_TRUE(meminfo.pgmajfault == 487192);
+ EXPECT_TRUE(ParseProcVmstat(valid_input2, &meminfo));
+ EXPECT_TRUE(meminfo.pswpin == 12);
+ EXPECT_TRUE(meminfo.pswpout == 901);
+ EXPECT_TRUE(meminfo.pgmajfault == 2023);
+}
+#endif // defined(OS_LINUX) || defined(OS_ANDROID)
+
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+TEST(SystemMetrics2Test, GetSystemMemoryInfo) {
+ base::SystemMemoryInfoKB info;
+ EXPECT_TRUE(base::GetSystemMemoryInfo(&info));
+
+ // Ensure each field received a value.
+ EXPECT_GT(info.total, 0);
+ EXPECT_GT(info.free, 0);
+ EXPECT_GT(info.buffers, 0);
+ EXPECT_GT(info.cached, 0);
+ EXPECT_GT(info.active_anon, 0);
+ EXPECT_GT(info.inactive_anon, 0);
+ EXPECT_GT(info.active_file, 0);
+ EXPECT_GT(info.inactive_file, 0);
+
+ // All the values should be less than the total amount of memory.
+ EXPECT_LT(info.free, info.total);
+ EXPECT_LT(info.buffers, info.total);
+ EXPECT_LT(info.cached, info.total);
+ EXPECT_LT(info.active_anon, info.total);
+ EXPECT_LT(info.inactive_anon, info.total);
+ EXPECT_LT(info.active_file, info.total);
+ EXPECT_LT(info.inactive_file, info.total);
+
+#if defined(OS_CHROMEOS)
+ // Chrome OS exposes shmem.
+ EXPECT_GT(info.shmem, 0);
+ EXPECT_LT(info.shmem, info.total);
+ // Chrome unit tests are not run on actual Chrome OS hardware, so gem_objects
+ // and gem_size cannot be tested here.
+#endif
+}
+#endif // defined(OS_LINUX) || defined(OS_ANDROID)
+
+#if defined(OS_WIN)
+// TODO(estade): if possible, port this test.
+TEST(ProcessMetricsTest, CalcFreeMemory) {
+ scoped_ptr<base::ProcessMetrics> metrics(
+ base::ProcessMetrics::CreateProcessMetrics(::GetCurrentProcess()));
+ ASSERT_TRUE(NULL != metrics.get());
+
+ bool using_tcmalloc = false;
+
+ // Detect if we are using tcmalloc
+#if !defined(NO_TCMALLOC)
+ const char* chrome_allocator = getenv("CHROME_ALLOCATOR");
+ if (!chrome_allocator || _stricmp(chrome_allocator, "tcmalloc") == 0)
+ using_tcmalloc = true;
+#endif
+
+ // Typical values here is ~1900 for total and ~1000 for largest. Obviously
+ // it depends in what other tests have done to this process.
+ base::FreeMBytes free_mem1 = {0};
+ EXPECT_TRUE(metrics->CalculateFreeMemory(&free_mem1));
+ EXPECT_LT(10u, free_mem1.total);
+ EXPECT_LT(10u, free_mem1.largest);
+ EXPECT_GT(2048u, free_mem1.total);
+ EXPECT_GT(2048u, free_mem1.largest);
+ EXPECT_GE(free_mem1.total, free_mem1.largest);
+ EXPECT_TRUE(NULL != free_mem1.largest_ptr);
+
+ // Allocate 20M and check again. It should have gone down.
+ const int kAllocMB = 20;
+ scoped_ptr<char[]> alloc(new char[kAllocMB * 1024 * 1024]);
+ size_t expected_total = free_mem1.total - kAllocMB;
+ size_t expected_largest = free_mem1.largest;
+
+ base::FreeMBytes free_mem2 = {0};
+ EXPECT_TRUE(metrics->CalculateFreeMemory(&free_mem2));
+ EXPECT_GE(free_mem2.total, free_mem2.largest);
+ // This test is flaky when using tcmalloc, because tcmalloc
+ // allocation strategy sometimes results in less than the
+ // full drop of 20Mb of free memory.
+ if (!using_tcmalloc)
+ EXPECT_GE(expected_total, free_mem2.total);
+ EXPECT_GE(expected_largest, free_mem2.largest);
+ EXPECT_TRUE(NULL != free_mem2.largest_ptr);
+}
+#endif // defined(OS_WIN)
+
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+TEST(ProcessMetricsTest, ParseProcStatCPU) {
+ // /proc/self/stat for a process running "top".
+ const char kTopStat[] = "960 (top) S 16230 960 16230 34818 960 "
+ "4202496 471 0 0 0 "
+ "12 16 0 0 " // <- These are the goods.
+ "20 0 1 0 121946157 15077376 314 18446744073709551615 4194304 "
+ "4246868 140733983044336 18446744073709551615 140244213071219 "
+ "0 0 0 138047495 0 0 0 17 1 0 0 0 0 0";
+ EXPECT_EQ(12 + 16, base::ParseProcStatCPU(kTopStat));
+
+ // cat /proc/self/stat on a random other machine I have.
+ const char kSelfStat[] = "5364 (cat) R 5354 5364 5354 34819 5364 "
+ "0 142 0 0 0 "
+ "0 0 0 0 " // <- No CPU, apparently.
+ "16 0 1 0 1676099790 2957312 114 4294967295 134512640 134528148 "
+ "3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0";
+
+ EXPECT_EQ(0, base::ParseProcStatCPU(kSelfStat));
+}
+#endif // defined(OS_LINUX) || defined(OS_ANDROID)
+
+// Disable on Android because base_unittests runs inside a Dalvik VM that
+// starts and stop threads (crbug.com/175563).
+#if defined(OS_LINUX)
+TEST(ProcessMetricsTest, GetNumberOfThreads) {
+ const base::ProcessHandle current = base::GetCurrentProcessHandle();
+ const int initial_threads = base::GetNumberOfThreads(current);
+ ASSERT_GT(initial_threads, 0);
+ const int kNumAdditionalThreads = 10;
+ {
+ scoped_ptr<base::Thread> my_threads[kNumAdditionalThreads];
+ for (int i = 0; i < kNumAdditionalThreads; ++i) {
+ my_threads[i].reset(new base::Thread("GetNumberOfThreadsTest"));
+ my_threads[i]->Start();
+ ASSERT_EQ(base::GetNumberOfThreads(current), initial_threads + 1 + i);
+ }
+ }
+ // The Thread destructor will stop them.
+ ASSERT_EQ(initial_threads, base::GetNumberOfThreads(current));
+}
+#endif // defined(OS_LINUX)
+
+} // namespace debug
+} // namespace base
diff --git a/chromium/base/process/process_util_unittest_ios.cc b/chromium/base/process/process_metrics_unittest_ios.cc
index cad0f1b09f0..3e1ca35b18c 100644
--- a/chromium/base/process/process_util_unittest_ios.cc
+++ b/chromium/base/process/process_metrics_unittest_ios.cc
@@ -1,12 +1,13 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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 "base/memory/scoped_ptr.h"
#include "base/process/process_metrics.h"
+
+#include "base/memory/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
-TEST(ProcessUtilTestIos, Memory) {
+TEST(ProcessMetricsTestIos, Memory) {
scoped_ptr<base::ProcessMetrics> process_metrics(
base::ProcessMetrics::CreateProcessMetrics(
base::GetCurrentProcessHandle()));
diff --git a/chromium/base/process/process_metrics_unittests.cc b/chromium/base/process/process_metrics_unittests.cc
deleted file mode 100644
index 387d860eda5..00000000000
--- a/chromium/base/process/process_metrics_unittests.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2013 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 "base/process/process_metrics.h"
-
-#include <sstream>
-#include <string>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-
-namespace base {
-namespace debug {
-
-// Tests for SystemMetrics.
-// Exists as a class so it can be a friend of SystemMetrics.
-class SystemMetricsTest : public testing::Test {
- public:
- SystemMetricsTest() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SystemMetricsTest);
-};
-
-/////////////////////////////////////////////////////////////////////////////
-
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-TEST_F(SystemMetricsTest, IsValidDiskName) {
- std::string invalid_input1 = "";
- std::string invalid_input2 = "s";
- std::string invalid_input3 = "sdz+";
- std::string invalid_input4 = "hda0";
- std::string invalid_input5 = "mmcbl";
- std::string invalid_input6 = "mmcblka";
- std::string invalid_input7 = "mmcblkb";
- std::string invalid_input8 = "mmmblk0";
-
- EXPECT_FALSE(IsValidDiskName(invalid_input1));
- EXPECT_FALSE(IsValidDiskName(invalid_input2));
- EXPECT_FALSE(IsValidDiskName(invalid_input3));
- EXPECT_FALSE(IsValidDiskName(invalid_input4));
- EXPECT_FALSE(IsValidDiskName(invalid_input5));
- EXPECT_FALSE(IsValidDiskName(invalid_input6));
- EXPECT_FALSE(IsValidDiskName(invalid_input7));
- EXPECT_FALSE(IsValidDiskName(invalid_input8));
-
- std::string valid_input1 = "sda";
- std::string valid_input2 = "sdaaaa";
- std::string valid_input3 = "hdz";
- std::string valid_input4 = "mmcblk0";
- std::string valid_input5 = "mmcblk999";
-
- EXPECT_TRUE(IsValidDiskName(valid_input1));
- EXPECT_TRUE(IsValidDiskName(valid_input2));
- EXPECT_TRUE(IsValidDiskName(valid_input3));
- EXPECT_TRUE(IsValidDiskName(valid_input4));
- EXPECT_TRUE(IsValidDiskName(valid_input5));
-}
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
-
-} // namespace debug
-} // namespace base
diff --git a/chromium/base/process/process_util_unittest.cc b/chromium/base/process/process_util_unittest.cc
index 44be9f4a273..6bfc1d07388 100644
--- a/chromium/base/process/process_util_unittest.cc
+++ b/chromium/base/process/process_util_unittest.cc
@@ -19,7 +19,9 @@
#include "base/process/memory.h"
#include "base/process/process.h"
#include "base/process/process_metrics.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/waitable_event.h"
#include "base/test/multiprocess_test.h"
#include "base/test/test_timeouts.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
@@ -29,7 +31,6 @@
#include "testing/multiprocess_func_list.h"
#if defined(OS_LINUX)
-#include <glib.h>
#include <malloc.h>
#include <sched.h>
#endif
@@ -44,6 +45,7 @@
#endif
#if defined(OS_WIN)
#include <windows.h>
+#include "base/win/windows_version.h"
#endif
#if defined(OS_MACOSX)
#include <mach/vm_param.h>
@@ -54,12 +56,6 @@ using base::FilePath;
namespace {
-#if defined(OS_WIN)
-const wchar_t kProcessName[] = L"base_unittests.exe";
-#else
-const wchar_t kProcessName[] = L"base_unittests";
-#endif // defined(OS_WIN)
-
#if defined(OS_ANDROID)
const char kShellPath[] = "/system/bin/sh";
const char kPosixShell[] = "sh";
@@ -69,7 +65,6 @@ const char kPosixShell[] = "bash";
#endif
const char kSignalFileSlow[] = "SlowChildProcess.die";
-const char kSignalFileCrash[] = "CrashingChildProcess.die";
const char kSignalFileKill[] = "KilledChildProcess.die";
#if defined(OS_WIN)
@@ -221,6 +216,7 @@ TEST_F(ProcessUtilTest, GetProcId) {
// TODO(gspencer): turn this test process into a very small program
// with no symbols (instead of using the multiprocess testing
// framework) to reduce the ReportCrash overhead.
+const char kSignalFileCrash[] = "CrashingChildProcess.die";
MULTIPROCESS_TEST_MAIN(CrashingChildProcess) {
WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileCrash).c_str());
@@ -360,85 +356,8 @@ TEST_F(ProcessUtilTest, SetProcessBackgroundedSelf) {
EXPECT_EQ(old_priority, new_priority);
}
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-TEST_F(ProcessUtilTest, GetSystemMemoryInfo) {
- base::SystemMemoryInfoKB info;
- EXPECT_TRUE(base::GetSystemMemoryInfo(&info));
-
- // Ensure each field received a value.
- EXPECT_GT(info.total, 0);
- EXPECT_GT(info.free, 0);
- EXPECT_GT(info.buffers, 0);
- EXPECT_GT(info.cached, 0);
- EXPECT_GT(info.active_anon, 0);
- EXPECT_GT(info.inactive_anon, 0);
- EXPECT_GT(info.active_file, 0);
- EXPECT_GT(info.inactive_file, 0);
-
- // All the values should be less than the total amount of memory.
- EXPECT_LT(info.free, info.total);
- EXPECT_LT(info.buffers, info.total);
- EXPECT_LT(info.cached, info.total);
- EXPECT_LT(info.active_anon, info.total);
- EXPECT_LT(info.inactive_anon, info.total);
- EXPECT_LT(info.active_file, info.total);
- EXPECT_LT(info.inactive_file, info.total);
-
-#if defined(OS_CHROMEOS)
- // Chrome OS exposes shmem.
- EXPECT_GT(info.shmem, 0);
- EXPECT_LT(info.shmem, info.total);
- // Chrome unit tests are not run on actual Chrome OS hardware, so gem_objects
- // and gem_size cannot be tested here.
-#endif
-}
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
-
-// TODO(estade): if possible, port these 2 tests.
#if defined(OS_WIN)
-TEST_F(ProcessUtilTest, CalcFreeMemory) {
- scoped_ptr<base::ProcessMetrics> metrics(
- base::ProcessMetrics::CreateProcessMetrics(::GetCurrentProcess()));
- ASSERT_TRUE(NULL != metrics.get());
-
- bool using_tcmalloc = false;
-
- // Detect if we are using tcmalloc
-#if !defined(NO_TCMALLOC)
- const char* chrome_allocator = getenv("CHROME_ALLOCATOR");
- if (!chrome_allocator || _stricmp(chrome_allocator, "tcmalloc") == 0)
- using_tcmalloc = true;
-#endif
-
- // Typical values here is ~1900 for total and ~1000 for largest. Obviously
- // it depends in what other tests have done to this process.
- base::FreeMBytes free_mem1 = {0};
- EXPECT_TRUE(metrics->CalculateFreeMemory(&free_mem1));
- EXPECT_LT(10u, free_mem1.total);
- EXPECT_LT(10u, free_mem1.largest);
- EXPECT_GT(2048u, free_mem1.total);
- EXPECT_GT(2048u, free_mem1.largest);
- EXPECT_GE(free_mem1.total, free_mem1.largest);
- EXPECT_TRUE(NULL != free_mem1.largest_ptr);
-
- // Allocate 20M and check again. It should have gone down.
- const int kAllocMB = 20;
- scoped_ptr<char[]> alloc(new char[kAllocMB * 1024 * 1024]);
- size_t expected_total = free_mem1.total - kAllocMB;
- size_t expected_largest = free_mem1.largest;
-
- base::FreeMBytes free_mem2 = {0};
- EXPECT_TRUE(metrics->CalculateFreeMemory(&free_mem2));
- EXPECT_GE(free_mem2.total, free_mem2.largest);
- // This test is flaky when using tcmalloc, because tcmalloc
- // allocation strategy sometimes results in less than the
- // full drop of 20Mb of free memory.
- if (!using_tcmalloc)
- EXPECT_GE(expected_total, free_mem2.total);
- EXPECT_GE(expected_largest, free_mem2.largest);
- EXPECT_TRUE(NULL != free_mem2.largest_ptr);
-}
-
+// TODO(estade): if possible, port this test.
TEST_F(ProcessUtilTest, GetAppOutput) {
// Let's create a decently long message.
std::string message;
@@ -468,16 +387,64 @@ TEST_F(ProcessUtilTest, GetAppOutput) {
EXPECT_EQ("", output);
}
+// TODO(estade): if possible, port this test.
TEST_F(ProcessUtilTest, LaunchAsUser) {
base::UserTokenHandle token;
ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token));
- std::wstring cmdline =
- this->MakeCmdLine("SimpleChildProcess", false).GetCommandLineString();
base::LaunchOptions options;
options.as_user = token;
- EXPECT_TRUE(base::LaunchProcess(cmdline, options, NULL));
+ EXPECT_TRUE(base::LaunchProcess(
+ this->MakeCmdLine("SimpleChildProcess", false), options, NULL));
+}
+
+static const char kEventToTriggerHandleSwitch[] = "event-to-trigger-handle";
+
+MULTIPROCESS_TEST_MAIN(TriggerEventChildProcess) {
+ std::string handle_value_string =
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ kEventToTriggerHandleSwitch);
+ CHECK(!handle_value_string.empty());
+
+ uint64 handle_value_uint64;
+ CHECK(base::StringToUint64(handle_value_string, &handle_value_uint64));
+ // Give ownership of the handle to |event|.
+ base::WaitableEvent event(reinterpret_cast<HANDLE>(handle_value_uint64));
+
+ event.Signal();
+
+ return 0;
}
+TEST_F(ProcessUtilTest, InheritSpecifiedHandles) {
+ // Manually create the event, so that it can be inheritable.
+ SECURITY_ATTRIBUTES security_attributes = {};
+ security_attributes.nLength = static_cast<DWORD>(sizeof(security_attributes));
+ security_attributes.lpSecurityDescriptor = NULL;
+ security_attributes.bInheritHandle = true;
+
+ // Takes ownership of the event handle.
+ base::WaitableEvent event(
+ CreateEvent(&security_attributes, true, false, NULL));
+ base::HandlesToInheritVector handles_to_inherit;
+ handles_to_inherit.push_back(event.handle());
+ base::LaunchOptions options;
+ options.handles_to_inherit = &handles_to_inherit;
+
+ CommandLine cmd_line = MakeCmdLine("TriggerEventChildProcess", false);
+ cmd_line.AppendSwitchASCII(kEventToTriggerHandleSwitch,
+ base::Uint64ToString(reinterpret_cast<uint64>(event.handle())));
+
+ // This functionality actually requires Vista or later. Make sure that it
+ // fails properly on XP.
+ if (base::win::GetVersion() < base::win::VERSION_VISTA) {
+ EXPECT_FALSE(base::LaunchProcess(cmd_line, options, NULL));
+ return;
+ }
+
+ // Launch the process and wait for it to trigger the event.
+ ASSERT_TRUE(base::LaunchProcess(cmd_line, options, NULL));
+ EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
+}
#endif // defined(OS_WIN)
#if defined(OS_POSIX)
@@ -525,7 +492,7 @@ MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) {
int written = HANDLE_EINTR(write(write_pipe, &num_open_files,
sizeof(num_open_files)));
DCHECK_EQ(static_cast<size_t>(written), sizeof(num_open_files));
- int ret = HANDLE_EINTR(close(write_pipe));
+ int ret = IGNORE_EINTR(close(write_pipe));
DPCHECK(ret == 0);
return 0;
@@ -541,7 +508,7 @@ int ProcessUtilTest::CountOpenFDsInChild() {
base::ProcessHandle handle = this->SpawnChild(
"ProcessUtilsLeakFDChildProcess", fd_mapping_vec, false);
CHECK(handle);
- int ret = HANDLE_EINTR(close(fds[1]));
+ int ret = IGNORE_EINTR(close(fds[1]));
DPCHECK(ret == 0);
// Read number of open files in client process from pipe;
@@ -557,7 +524,7 @@ int ProcessUtilTest::CountOpenFDsInChild() {
CHECK(base::WaitForSingleProcess(handle, base::TimeDelta::FromSeconds(1)));
#endif
base::CloseProcessHandle(handle);
- ret = HANDLE_EINTR(close(fds[0]));
+ ret = IGNORE_EINTR(close(fds[0]));
DPCHECK(ret == 0);
return num_open_files;
@@ -585,11 +552,11 @@ TEST_F(ProcessUtilTest, MAYBE_FDRemapping) {
ASSERT_EQ(fds_after, fds_before);
int ret;
- ret = HANDLE_EINTR(close(sockets[0]));
+ ret = IGNORE_EINTR(close(sockets[0]));
DPCHECK(ret == 0);
- ret = HANDLE_EINTR(close(sockets[1]));
+ ret = IGNORE_EINTR(close(sockets[1]));
DPCHECK(ret == 0);
- ret = HANDLE_EINTR(close(dev_null));
+ ret = IGNORE_EINTR(close(dev_null));
DPCHECK(ret == 0);
}
@@ -618,13 +585,13 @@ std::string TestLaunchProcess(const base::EnvironmentMap& env_changes,
CHECK_EQ(0, clone_flags);
#endif // OS_LINUX
EXPECT_TRUE(base::LaunchProcess(args, options, NULL));
- PCHECK(HANDLE_EINTR(close(fds[1])) == 0);
+ PCHECK(IGNORE_EINTR(close(fds[1])) == 0);
char buf[512];
const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
PCHECK(n > 0);
- PCHECK(HANDLE_EINTR(close(fds[0])) == 0);
+ PCHECK(IGNORE_EINTR(close(fds[0])) == 0);
return std::string(buf, n);
}
@@ -775,7 +742,16 @@ TEST_F(ProcessUtilTest, GetAppOutputRestrictedSIGPIPE) {
}
#endif
-TEST_F(ProcessUtilTest, GetAppOutputRestrictedNoZombies) {
+#if defined(ADDRESS_SANITIZER) && defined(OS_MACOSX) && \
+ defined(ARCH_CPU_64_BITS)
+// Times out under AddressSanitizer on 64-bit OS X, see
+// http://crbug.com/298197.
+#define MAYBE_GetAppOutputRestrictedNoZombies \
+ DISABLED_GetAppOutputRestrictedNoZombies
+#else
+#define MAYBE_GetAppOutputRestrictedNoZombies GetAppOutputRestrictedNoZombies
+#endif
+TEST_F(ProcessUtilTest, MAYBE_GetAppOutputRestrictedNoZombies) {
std::vector<std::string> argv;
argv.push_back(std::string(kShellPath)); // argv[0]
@@ -826,50 +802,6 @@ TEST_F(ProcessUtilTest, GetParentProcessId) {
EXPECT_EQ(ppid, getppid());
}
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-TEST_F(ProcessUtilTest, ParseProcStatCPU) {
- // /proc/self/stat for a process running "top".
- const char kTopStat[] = "960 (top) S 16230 960 16230 34818 960 "
- "4202496 471 0 0 0 "
- "12 16 0 0 " // <- These are the goods.
- "20 0 1 0 121946157 15077376 314 18446744073709551615 4194304 "
- "4246868 140733983044336 18446744073709551615 140244213071219 "
- "0 0 0 138047495 0 0 0 17 1 0 0 0 0 0";
- EXPECT_EQ(12 + 16, base::ParseProcStatCPU(kTopStat));
-
- // cat /proc/self/stat on a random other machine I have.
- const char kSelfStat[] = "5364 (cat) R 5354 5364 5354 34819 5364 "
- "0 142 0 0 0 "
- "0 0 0 0 " // <- No CPU, apparently.
- "16 0 1 0 1676099790 2957312 114 4294967295 134512640 134528148 "
- "3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0";
-
- EXPECT_EQ(0, base::ParseProcStatCPU(kSelfStat));
-}
-
-// Disable on Android because base_unittests runs inside a Dalvik VM that
-// starts and stop threads (crbug.com/175563).
-#if !defined(OS_ANDROID)
-TEST_F(ProcessUtilTest, GetNumberOfThreads) {
- const base::ProcessHandle current = base::GetCurrentProcessHandle();
- const int initial_threads = base::GetNumberOfThreads(current);
- ASSERT_GT(initial_threads, 0);
- const int kNumAdditionalThreads = 10;
- {
- scoped_ptr<base::Thread> my_threads[kNumAdditionalThreads];
- for (int i = 0; i < kNumAdditionalThreads; ++i) {
- my_threads[i].reset(new base::Thread("GetNumberOfThreadsTest"));
- my_threads[i]->Start();
- ASSERT_EQ(base::GetNumberOfThreads(current), initial_threads + 1 + i);
- }
- }
- // The Thread destructor will stop them.
- ASSERT_EQ(initial_threads, base::GetNumberOfThreads(current));
-}
-#endif // !defined(OS_ANDROID)
-
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
-
// TODO(port): port those unit tests.
bool IsProcessDead(base::ProcessHandle child) {
// waitpid() will actually reap the process which is exactly NOT what we