summaryrefslogtreecommitdiffstats
path: root/chromium/base/process
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-10-13 13:24:50 +0200
committerAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-10-14 10:57:25 +0000
commitaf3d4809763ef308f08ced947a73b624729ac7ea (patch)
tree4402b911e30383f6c6dace1e8cf3b8e85355db3a /chromium/base/process
parent0e8ff63a407fe323e215bb1a2c423c09a4747c8a (diff)
BASELINE: Update Chromium to 47.0.2526.14
Also adding in sources needed for spellchecking. Change-Id: Idd44170fa1616f26315188970a8d5ba7d472b18a Reviewed-by: Michael BrĂ¼ning <michael.bruning@theqtcompany.com>
Diffstat (limited to 'chromium/base/process')
-rw-r--r--chromium/base/process/BUILD.gn7
-rw-r--r--chromium/base/process/internal_linux.cc5
-rw-r--r--chromium/base/process/kill.h1
-rw-r--r--chromium/base/process/kill_win.cc2
-rw-r--r--chromium/base/process/launch.h21
-rw-r--r--chromium/base/process/launch_mac.cc17
-rw-r--r--chromium/base/process/launch_posix.cc38
-rw-r--r--chromium/base/process/launch_win.cc188
-rw-r--r--chromium/base/process/memory_mac.mm5
-rw-r--r--chromium/base/process/memory_unittest.cc78
-rw-r--r--chromium/base/process/memory_win.cc30
-rw-r--r--chromium/base/process/port_provider_mac.h29
-rw-r--r--chromium/base/process/process.h20
-rw-r--r--chromium/base/process/process_info_linux.cc2
-rw-r--r--chromium/base/process/process_info_mac.cc2
-rw-r--r--chromium/base/process/process_iterator_mac.cc3
-rw-r--r--chromium/base/process/process_linux.cc4
-rw-r--r--chromium/base/process/process_mac.cc128
-rw-r--r--chromium/base/process/process_metrics.h84
-rw-r--r--chromium/base/process/process_metrics_ios.cc12
-rw-r--r--chromium/base/process/process_metrics_linux.cc13
-rw-r--r--chromium/base/process/process_metrics_mac.cc37
-rw-r--r--chromium/base/process/process_metrics_unittest.cc10
-rw-r--r--chromium/base/process/process_metrics_win.cc37
-rw-r--r--chromium/base/process/process_posix.cc14
-rw-r--r--chromium/base/process/process_unittest.cc32
-rw-r--r--chromium/base/process/process_util_unittest.cc19
-rw-r--r--chromium/base/process/process_win.cc20
28 files changed, 456 insertions, 402 deletions
diff --git a/chromium/base/process/BUILD.gn b/chromium/base/process/BUILD.gn
index 3978b2e58cf..eabbde538f1 100644
--- a/chromium/base/process/BUILD.gn
+++ b/chromium/base/process/BUILD.gn
@@ -22,6 +22,7 @@ source_set("process") {
"memory_linux.cc",
"memory_mac.mm",
"memory_win.cc",
+ "port_provider_mac.h",
"process.h",
"process_handle_freebsd.cc",
"process_handle_linux.cc",
@@ -41,7 +42,6 @@ source_set("process") {
"process_iterator_openbsd.cc",
"process_iterator_win.cc",
"process_linux.cc",
- "process_mac.cc",
"process_metrics.cc",
"process_metrics.h",
"process_metrics_freebsd.cc",
@@ -96,7 +96,10 @@ source_set("process") {
}
if (is_ios) {
- sources += [ "process_metrics.cc" ]
+ sources += [
+ "memory_stubs.cc",
+ "process_metrics.cc",
+ ]
}
configs += [ "//base:base_implementation" ]
diff --git a/chromium/base/process/internal_linux.cc b/chromium/base/process/internal_linux.cc
index 4f3fcaccbfb..e6c2119c141 100644
--- a/chromium/base/process/internal_linux.cc
+++ b/chromium/base/process/internal_linux.cc
@@ -97,8 +97,9 @@ bool ParseProcStats(const std::string& stats_data,
close_parens_idx - (open_parens_idx + 1)));
// Split the rest.
- std::vector<std::string> other_stats;
- SplitString(stats_data.substr(close_parens_idx + 2), ' ', &other_stats);
+ std::vector<std::string> other_stats = SplitString(
+ stats_data.substr(close_parens_idx + 2), " ",
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
for (size_t i = 0; i < other_stats.size(); ++i)
proc_stats->push_back(other_stats[i]);
return true;
diff --git a/chromium/base/process/kill.h b/chromium/base/process/kill.h
index dbd32e17058..bb4103fb643 100644
--- a/chromium/base/process/kill.h
+++ b/chromium/base/process/kill.h
@@ -37,6 +37,7 @@ enum TerminationStatus {
// a hint.
TERMINATION_STATUS_OOM_PROTECTED, // child was protected from oom kill
#endif
+ TERMINATION_STATUS_LAUNCH_FAILED, // child process never launched
TERMINATION_STATUS_MAX_ENUM
};
diff --git a/chromium/base/process/kill_win.cc b/chromium/base/process/kill_win.cc
index 0da3a26ae4f..7cbf9489051 100644
--- a/chromium/base/process/kill_win.cc
+++ b/chromium/base/process/kill_win.cc
@@ -57,7 +57,7 @@ class TimerExpiredTask : public win::ObjectWatcher::Delegate {
};
TimerExpiredTask::TimerExpiredTask(Process process) : process_(process.Pass()) {
- watcher_.StartWatching(process_.Handle(), this);
+ watcher_.StartWatchingOnce(process_.Handle(), this);
}
TimerExpiredTask::~TimerExpiredTask() {
diff --git a/chromium/base/process/launch.h b/chromium/base/process/launch.h
index 0e42cd006ff..42b8a7670d9 100644
--- a/chromium/base/process/launch.h
+++ b/chromium/base/process/launch.h
@@ -164,16 +164,6 @@ struct BASE_EXPORT LaunchOptions {
// process' controlling terminal.
int ctrl_terminal_fd;
#endif // defined(OS_CHROMEOS)
-
-#if defined(OS_MACOSX)
- // If this name is non-empty, the new child, after fork() but before exec(),
- // will look up this server name in the bootstrap namespace. The resulting
- // service port will be replaced as the bootstrap port in the child. Because
- // the process's IPC space is cleared on exec(), any rights to the old
- // bootstrap port will not be transferred to the new process.
- std::string replacement_bootstrap_name;
-#endif
-
#endif // !defined(OS_WIN)
};
@@ -236,7 +226,7 @@ BASE_EXPORT bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags);
// Output multi-process printf, cout, cerr, etc to the cmd.exe console that ran
// chrome. This is not thread-safe: only call from main thread.
-BASE_EXPORT void RouteStdioToConsole();
+BASE_EXPORT void RouteStdioToConsole(bool create_console_if_not_found);
#endif // defined(OS_WIN)
// Executes the application specified by |cl| and wait for it to exit. Stores
@@ -245,6 +235,10 @@ BASE_EXPORT void RouteStdioToConsole();
// indicating success).
BASE_EXPORT bool GetAppOutput(const CommandLine& cl, std::string* output);
+// Like GetAppOutput, but also includes stderr.
+BASE_EXPORT bool GetAppOutputAndError(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
@@ -286,11 +280,6 @@ BASE_EXPORT void RaiseProcessToHighPriority();
// in the child after forking will restore the standard exception handler.
// See http://crbug.com/20371/ for more details.
void RestoreDefaultExceptionHandler();
-
-// Look up the bootstrap server named |replacement_bootstrap_name| via the
-// current |bootstrap_port|. Then replace the task's bootstrap port with the
-// received right.
-void ReplaceBootstrapPort(const std::string& replacement_bootstrap_name);
#endif // defined(OS_MACOSX)
// Creates a LaunchOptions object suitable for launching processes in a test
diff --git a/chromium/base/process/launch_mac.cc b/chromium/base/process/launch_mac.cc
index ce02475541e..5895eae4351 100644
--- a/chromium/base/process/launch_mac.cc
+++ b/chromium/base/process/launch_mac.cc
@@ -28,21 +28,4 @@ void RestoreDefaultExceptionHandler() {
EXCEPTION_DEFAULT, THREAD_STATE_NONE);
}
-void ReplaceBootstrapPort(const std::string& new_bootstrap_name) {
- // This function is called between fork() and exec(), so it should take care
- // to run properly in that situation.
-
- mach_port_t port = MACH_PORT_NULL;
- kern_return_t kr = bootstrap_look_up(bootstrap_port,
- new_bootstrap_name.c_str(), &port);
- if (kr != KERN_SUCCESS) {
- RAW_LOG(FATAL, "Failed to look up replacement bootstrap port.");
- }
-
- kr = task_set_bootstrap_port(mach_task_self(), port);
- if (kr != KERN_SUCCESS) {
- RAW_LOG(FATAL, "Failed to replace bootstrap port.");
- }
-}
-
} // namespace base
diff --git a/chromium/base/process/launch_posix.cc b/chromium/base/process/launch_posix.cc
index 99d8e3aa64d..f076733d783 100644
--- a/chromium/base/process/launch_posix.cc
+++ b/chromium/base/process/launch_posix.cc
@@ -22,7 +22,6 @@
#include <limits>
#include <set>
-#include "base/allocator/type_profiler_control.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/debug/debugger.h"
@@ -392,11 +391,6 @@ Process LaunchProcess(const std::vector<std::string>& argv,
}
}
- // Stop type-profiler.
- // The profiler should be stopped between fork and exec since it inserts
- // locks at new/delete expressions. See http://crbug.com/36678.
- base::type_profiler::Controller::Stop();
-
if (options.maximize_rlimits) {
// Some resource limits need to be maximal in this child.
for (size_t i = 0; i < options.maximize_rlimits->size(); ++i) {
@@ -415,8 +409,6 @@ Process LaunchProcess(const std::vector<std::string>& argv,
#if defined(OS_MACOSX)
RestoreDefaultExceptionHandler();
- if (!options.replacement_bootstrap_name.empty())
- ReplaceBootstrapPort(options.replacement_bootstrap_name);
#endif // defined(OS_MACOSX)
ResetChildSignalHandlersToDefaults();
@@ -530,7 +522,8 @@ enum GetAppOutputInternalResult {
// path for the application; in that case, |envp| must be null, and it will use
// the current environment. If |do_search_path| is false, |argv[0]| should fully
// specify the path of the application, and |envp| will be used as the
-// environment. Redirects stderr to /dev/null.
+// environment. If |include_stderr| is true, includes stderr otherwise redirects
+// it to /dev/null.
// If we successfully start the application and get all requested output, we
// return GOT_MAX_OUTPUT, or if there is a problem starting or exiting
// the application we return RUN_FAILURE. Otherwise we return EXECUTE_SUCCESS.
@@ -543,6 +536,7 @@ enum GetAppOutputInternalResult {
static GetAppOutputInternalResult GetAppOutputInternal(
const std::vector<std::string>& argv,
char* const envp[],
+ bool include_stderr,
std::string* output,
size_t max_output,
bool do_search_path,
@@ -591,13 +585,10 @@ static GetAppOutputInternalResult GetAppOutputInternal(
if (dev_null < 0)
_exit(127);
- // Stop type-profiler.
- // The profiler should be stopped between fork and exec since it inserts
- // locks at new/delete expressions. See http://crbug.com/36678.
- base::type_profiler::Controller::Stop();
-
fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
- fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true));
+ fd_shuffle1.push_back(InjectionArc(
+ include_stderr ? pipe_fd[1] : dev_null,
+ STDERR_FILENO, true));
fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true));
// Adding another element here? Remeber to increase the argument to
// reserve(), above.
@@ -666,11 +657,20 @@ bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) {
// Run |execve()| with the current environment and store "unlimited" data.
int exit_code;
GetAppOutputInternalResult result = GetAppOutputInternal(
- argv, NULL, output, std::numeric_limits<std::size_t>::max(), true,
+ argv, NULL, false, output, std::numeric_limits<std::size_t>::max(), true,
&exit_code);
return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS;
}
+bool GetAppOutputAndError(const CommandLine& cl, std::string* output) {
+ // Run |execve()| with the current environment and store "unlimited" data.
+ int exit_code;
+ GetAppOutputInternalResult result = GetAppOutputInternal(
+ cl.argv(), NULL, true, output, std::numeric_limits<std::size_t>::max(),
+ true, &exit_code);
+ return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS;
+}
+
// TODO(viettrungluu): Conceivably, we should have a timeout as well, so we
// don't hang if what we're calling hangs.
bool GetAppOutputRestricted(const CommandLine& cl,
@@ -679,7 +679,7 @@ bool GetAppOutputRestricted(const CommandLine& cl,
char* const empty_environ = NULL;
int exit_code;
GetAppOutputInternalResult result = GetAppOutputInternal(
- cl.argv(), &empty_environ, output, max_output, false, &exit_code);
+ cl.argv(), &empty_environ, false, output, max_output, false, &exit_code);
return result == GOT_MAX_OUTPUT || (result == EXECUTE_SUCCESS &&
exit_code == EXIT_SUCCESS);
}
@@ -689,8 +689,8 @@ bool GetAppOutputWithExitCode(const CommandLine& cl,
int* exit_code) {
// Run |execve()| with the current environment and store "unlimited" data.
GetAppOutputInternalResult result = GetAppOutputInternal(
- cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true,
- exit_code);
+ cl.argv(), NULL, false, output, std::numeric_limits<std::size_t>::max(),
+ true, exit_code);
return result == EXECUTE_SUCCESS;
}
diff --git a/chromium/base/process/launch_win.cc b/chromium/base/process/launch_win.cc
index fa59f1ae907..54b06675100 100644
--- a/chromium/base/process/launch_win.cc
+++ b/chromium/base/process/launch_win.cc
@@ -46,9 +46,91 @@ namespace {
// process goes away.
const DWORD kProcessKilledExitCode = 1;
+bool GetAppOutputInternal(const StringPiece16& cl,
+ bool include_stderr,
+ std::string* output) {
+ HANDLE out_read = NULL;
+ HANDLE out_write = NULL;
+
+ SECURITY_ATTRIBUTES sa_attr;
+ // Set the bInheritHandle flag so pipe handles are inherited.
+ sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa_attr.bInheritHandle = TRUE;
+ sa_attr.lpSecurityDescriptor = NULL;
+
+ // Create the pipe for the child process's STDOUT.
+ if (!CreatePipe(&out_read, &out_write, &sa_attr, 0)) {
+ NOTREACHED() << "Failed to create pipe";
+ return false;
+ }
+
+ // Ensure we don't leak the handles.
+ win::ScopedHandle scoped_out_read(out_read);
+ win::ScopedHandle scoped_out_write(out_write);
+
+ // Ensure the read handles to the pipes are not inherited.
+ if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) {
+ NOTREACHED() << "Failed to disabled pipe inheritance";
+ return false;
+ }
+
+ FilePath::StringType writable_command_line_string;
+ writable_command_line_string.assign(cl.data(), cl.size());
+
+ STARTUPINFO start_info = {};
+
+ start_info.cb = sizeof(STARTUPINFO);
+ start_info.hStdOutput = out_write;
+ // Keep the normal stdin.
+ start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ if (include_stderr) {
+ start_info.hStdError = out_write;
+ } else {
+ start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ }
+ 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, &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.
+ scoped_out_write.Close();
+
+ // Read output from the child process's pipe for STDOUT
+ const int kBufferSize = 1024;
+ char buffer[kBufferSize];
+
+ for (;;) {
+ DWORD bytes_read = 0;
+ BOOL success = ReadFile(out_read, buffer, kBufferSize, &bytes_read, NULL);
+ if (!success || bytes_read == 0)
+ break;
+ output->append(buffer, bytes_read);
+ }
+
+ // Let's wait for the process to finish.
+ WaitForSingleObject(proc_info.process_handle(), INFINITE);
+
+ int exit_code;
+ base::TerminationStatus status = GetTerminationStatus(
+ proc_info.process_handle(), &exit_code);
+ return status != base::TERMINATION_STATUS_PROCESS_CRASHED &&
+ status != base::TERMINATION_STATUS_ABNORMAL_TERMINATION;
+}
+
} // namespace
-void RouteStdioToConsole() {
+void RouteStdioToConsole(bool create_console_if_not_found) {
// Don't change anything if stdout or stderr already point to a
// valid stream.
//
@@ -64,8 +146,22 @@ void RouteStdioToConsole() {
// stdout/stderr on startup (before the handle IDs can be reused).
// _fileno(stdout) will return -2 (_NO_CONSOLE_FILENO) if stdout was
// invalid.
- if (_fileno(stdout) >= 0 || _fileno(stderr) >= 0)
- return;
+ if (_fileno(stdout) >= 0 || _fileno(stderr) >= 0) {
+ // _fileno was broken for SUBSYSTEM:WINDOWS from VS2010 to VS2012/2013.
+ // http://crbug.com/358267. Confirm that the underlying HANDLE is valid
+ // before aborting.
+
+ // This causes NaCl tests to hang on XP for reasons unclear, perhaps due
+ // to not being able to inherit handles. Since it's only for debugging,
+ // and redirecting still works, punt for now.
+ if (base::win::GetVersion() < base::win::VERSION_VISTA)
+ return;
+
+ intptr_t stdout_handle = _get_osfhandle(_fileno(stdout));
+ intptr_t stderr_handle = _get_osfhandle(_fileno(stderr));
+ if (stdout_handle >= 0 || stderr_handle >= 0)
+ return;
+ }
if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
unsigned int result = GetLastError();
@@ -76,10 +172,14 @@ void RouteStdioToConsole() {
// parent process is invalid (eg: crashed).
if (result == ERROR_GEN_FAILURE)
return;
- // Make a new console if attaching to parent fails with any other error.
- // It should be ERROR_INVALID_HANDLE at this point, which means the browser
- // was likely not started from a console.
- AllocConsole();
+ if (create_console_if_not_found) {
+ // Make a new console if attaching to parent fails with any other error.
+ // It should be ERROR_INVALID_HANDLE at this point, which means the
+ // browser was likely not started from a console.
+ AllocConsole();
+ } else {
+ return;
+ }
}
// Arbitrary byte count to use when buffering output lines. More
@@ -274,76 +374,12 @@ 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;
-
- SECURITY_ATTRIBUTES sa_attr;
- // Set the bInheritHandle flag so pipe handles are inherited.
- sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa_attr.bInheritHandle = TRUE;
- sa_attr.lpSecurityDescriptor = NULL;
-
- // Create the pipe for the child process's STDOUT.
- if (!CreatePipe(&out_read, &out_write, &sa_attr, 0)) {
- NOTREACHED() << "Failed to create pipe";
- return false;
- }
-
- // Ensure we don't leak the handles.
- win::ScopedHandle scoped_out_read(out_read);
- win::ScopedHandle scoped_out_write(out_write);
-
- // Ensure the read handle to the pipe for STDOUT is not inherited.
- if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) {
- NOTREACHED() << "Failed to disabled pipe inheritance";
- return false;
- }
-
- FilePath::StringType writable_command_line_string;
- writable_command_line_string.assign(cl.data(), cl.size());
-
- STARTUPINFO start_info = {};
-
- start_info.cb = sizeof(STARTUPINFO);
- start_info.hStdOutput = out_write;
- // Keep the normal stdin and stderr.
- start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- 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, &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.
- scoped_out_write.Close();
-
- // Read output from the child process's pipe for STDOUT
- const int kBufferSize = 1024;
- char buffer[kBufferSize];
-
- for (;;) {
- DWORD bytes_read = 0;
- BOOL success = ReadFile(out_read, buffer, kBufferSize, &bytes_read, NULL);
- if (!success || bytes_read == 0)
- break;
- output->append(buffer, bytes_read);
- }
-
- // Let's wait for the process to finish.
- WaitForSingleObject(proc_info.process_handle(), INFINITE);
+bool GetAppOutputAndError(const CommandLine& cl, std::string* output) {
+ return GetAppOutputInternal(cl.GetCommandLineString(), true, output);
+}
- return true;
+bool GetAppOutput(const StringPiece16& cl, std::string* output) {
+ return GetAppOutputInternal(cl, false, output);
}
void RaiseProcessToHighPriority() {
diff --git a/chromium/base/process/memory_mac.mm b/chromium/base/process/memory_mac.mm
index 4d719f8054e..17249a239b9 100644
--- a/chromium/base/process/memory_mac.mm
+++ b/chromium/base/process/memory_mac.mm
@@ -246,7 +246,7 @@ void oom_killer_new() {
// === Core Foundation CFAllocators ===
bool CanGetContextForCFAllocator() {
- return !base::mac::IsOSLaterThanYosemite_DontCallThis();
+ return !base::mac::IsOSLaterThanElCapitan_DontCallThis();
}
CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) {
@@ -258,7 +258,8 @@ CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) {
} else if (base::mac::IsOSLion() ||
base::mac::IsOSMountainLion() ||
base::mac::IsOSMavericks() ||
- base::mac::IsOSYosemite()) {
+ base::mac::IsOSYosemite() ||
+ base::mac::IsOSElCapitan()) {
ChromeCFAllocatorLions* our_allocator =
const_cast<ChromeCFAllocatorLions*>(
reinterpret_cast<const ChromeCFAllocatorLions*>(allocator));
diff --git a/chromium/base/process/memory_unittest.cc b/chromium/base/process/memory_unittest.cc
index 0276b495915..98f049a3bf9 100644
--- a/chromium/base/process/memory_unittest.cc
+++ b/chromium/base/process/memory_unittest.cc
@@ -30,6 +30,16 @@
#endif
#if defined(OS_WIN)
+
+#if defined(_MSC_VER)
+// ssize_t needed for OutOfMemoryTest.
+#if defined(_WIN64)
+typedef __int64 ssize_t;
+#else
+typedef long ssize_t;
+#endif
+#endif
+
// HeapQueryInformation function pointer.
typedef BOOL (WINAPI* HeapQueryFn) \
(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T);
@@ -130,8 +140,9 @@ TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) {
// OutOfMemoryTest cases. OpenBSD does not support these tests either.
// Don't test these on ASan/TSan/MSan configurations: only test the real
// allocator.
-// TODO(vandebo) make this work on Windows too.
-#if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !defined(OS_WIN) && \
+// Windows only supports these tests with the allocator shim in place.
+#if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && \
+ !(defined(OS_WIN) && !defined(ALLOCATOR_SHIM)) && \
!defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
#if defined(USE_TCMALLOC)
@@ -151,6 +162,9 @@ class OutOfMemoryTest : public testing::Test {
// Make test size as large as possible minus a few pages so
// that alignment or other rounding doesn't make it wrap.
test_size_(std::numeric_limits<std::size_t>::max() - 12 * 1024),
+ // A test size that is > 2Gb and will cause the allocators to reject
+ // the allocation due to security restrictions. See crbug.com/169327.
+ insecure_test_size_(std::numeric_limits<int>::max()),
signed_test_size_(std::numeric_limits<ssize_t>::max()) {
}
@@ -163,6 +177,7 @@ class OutOfMemoryTest : public testing::Test {
protected:
void* value_;
size_t test_size_;
+ size_t insecure_test_size_;
ssize_t signed_test_size_;
};
@@ -213,6 +228,47 @@ TEST_F(OutOfMemoryDeathTest, Calloc) {
}, kOomRegex);
}
+// OS X has no 2Gb allocation limit.
+// See https://crbug.com/169327.
+#if !defined(OS_MACOSX)
+TEST_F(OutOfMemoryDeathTest, SecurityNew) {
+ ASSERT_DEATH({
+ SetUpInDeathAssert();
+ value_ = operator new(insecure_test_size_);
+ }, kOomRegex);
+}
+
+TEST_F(OutOfMemoryDeathTest, SecurityNewArray) {
+ ASSERT_DEATH({
+ SetUpInDeathAssert();
+ value_ = new char[insecure_test_size_];
+ }, kOomRegex);
+}
+
+TEST_F(OutOfMemoryDeathTest, SecurityMalloc) {
+ ASSERT_DEATH({
+ SetUpInDeathAssert();
+ value_ = malloc(insecure_test_size_);
+ }, kOomRegex);
+}
+
+TEST_F(OutOfMemoryDeathTest, SecurityRealloc) {
+ ASSERT_DEATH({
+ SetUpInDeathAssert();
+ value_ = realloc(NULL, insecure_test_size_);
+ }, kOomRegex);
+}
+
+TEST_F(OutOfMemoryDeathTest, SecurityCalloc) {
+ ASSERT_DEATH({
+ SetUpInDeathAssert();
+ value_ = calloc(1024, insecure_test_size_ / 1024L);
+ }, kOomRegex);
+}
+#endif // !defined(OS_MACOSX)
+
+#if defined(OS_LINUX)
+
TEST_F(OutOfMemoryDeathTest, Valloc) {
ASSERT_DEATH({
SetUpInDeathAssert();
@@ -220,7 +276,12 @@ TEST_F(OutOfMemoryDeathTest, Valloc) {
}, kOomRegex);
}
-#if defined(OS_LINUX)
+TEST_F(OutOfMemoryDeathTest, SecurityValloc) {
+ ASSERT_DEATH({
+ SetUpInDeathAssert();
+ value_ = valloc(insecure_test_size_);
+ }, kOomRegex);
+}
#if PVALLOC_AVAILABLE == 1
TEST_F(OutOfMemoryDeathTest, Pvalloc) {
@@ -229,6 +290,13 @@ TEST_F(OutOfMemoryDeathTest, Pvalloc) {
value_ = pvalloc(test_size_);
}, kOomRegex);
}
+
+TEST_F(OutOfMemoryDeathTest, SecurityPvalloc) {
+ ASSERT_DEATH({
+ SetUpInDeathAssert();
+ value_ = pvalloc(insecure_test_size_);
+ }, kOomRegex);
+}
#endif // PVALLOC_AVAILABLE == 1
TEST_F(OutOfMemoryDeathTest, Memalign) {
@@ -415,5 +483,5 @@ TEST_F(OutOfMemoryHandledTest, UncheckedCalloc) {
EXPECT_TRUE(value_ == NULL);
}
#endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-#endif // !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !defined(OS_WIN) &&
- // !defined(ADDRESS_SANITIZER)
+#endif // !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !(defined(OS_WIN) &&
+ // !defined(ALLOCATOR_SHIM)) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
diff --git a/chromium/base/process/memory_win.cc b/chromium/base/process/memory_win.cc
index fc57b48f1f7..b949b5d8854 100644
--- a/chromium/base/process/memory_win.cc
+++ b/chromium/base/process/memory_win.cc
@@ -10,6 +10,21 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+// malloc_unchecked is required to implement UncheckedMalloc properly.
+// It's provided by allocator_shim_win.cc but since that's not always present,
+// we provide a default that falls back to regular malloc.
+typedef void* (*MallocFn)(size_t);
+extern "C" void* (*const malloc_unchecked)(size_t);
+extern "C" void* (*const malloc_default)(size_t) = &malloc;
+
+#if defined(_M_IX86)
+#pragma comment(linker, "/alternatename:_malloc_unchecked=_malloc_default")
+#elif defined(_M_X64) || defined(_M_ARM)
+#pragma comment(linker, "/alternatename:malloc_unchecked=malloc_default")
+#else
+#error Unsupported platform
+#endif
+
namespace base {
namespace {
@@ -17,10 +32,12 @@ namespace {
#pragma warning(push)
#pragma warning(disable: 4702)
-int OnNoMemory(size_t) {
+int OnNoMemory(size_t size) {
// Kill the process. This is important for security since most of code
// does not check the result of memory allocation.
- __debugbreak();
+ LOG(FATAL) << "Out of memory, size = " << size;
+
+ // Safety check, make sure process exits here.
_exit(1);
return 0;
}
@@ -88,14 +105,9 @@ HMODULE GetModuleFromAddress(void* address) {
return instance;
}
-// TODO(b.kelemen): implement it with the required semantics. On Linux this is
-// implemented with a weak symbol that is overridden by tcmalloc. This is
-// neccessary because base cannot have a direct dependency on tcmalloc. Since
-// weak symbols are not supported on Windows this will involve some build time
-// magic, much like what is done for libcrt in order to override the allocation
-// functions.
+// Implemented using a weak symbol.
bool UncheckedMalloc(size_t size, void** result) {
- *result = malloc(size);
+ *result = malloc_unchecked(size);
return *result != NULL;
}
diff --git a/chromium/base/process/port_provider_mac.h b/chromium/base/process/port_provider_mac.h
new file mode 100644
index 00000000000..bdee4a8a293
--- /dev/null
+++ b/chromium/base/process/port_provider_mac.h
@@ -0,0 +1,29 @@
+// Copyright 2015 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.
+
+#ifndef BASE_PROCESS_PORT_PROVIDER_MAC_H_
+#define BASE_PROCESS_PORT_PROVIDER_MAC_H_
+
+#include <mach/mach.h>
+
+#include "base/base_export.h"
+#include "base/process/process_handle.h"
+
+namespace base {
+
+// Abstract base class that provides a mapping from ProcessHandle (pid_t) to the
+// Mach task port. This replicates task_for_pid(), which requires root
+// privileges.
+class BASE_EXPORT PortProvider {
+ public:
+ virtual ~PortProvider() {}
+
+ // Returns the mach task port for |process| if possible, or else
+ // |MACH_PORT_NULL|.
+ virtual mach_port_t TaskForPid(ProcessHandle process) const = 0;
+};
+
+} // namespace base
+
+#endif // BASE_PROCESS_PORT_PROVIDER_MAC_H_
diff --git a/chromium/base/process/process.h b/chromium/base/process/process.h
index 1559554c011..2a83cb088ac 100644
--- a/chromium/base/process/process.h
+++ b/chromium/base/process/process.h
@@ -111,24 +111,6 @@ class BASE_EXPORT Process {
// is not required.
bool WaitForExitWithTimeout(TimeDelta timeout, int* exit_code);
-#if defined(OS_MACOSX)
- // The Mac needs a Mach port in order to manipulate a process's priority,
- // and there's no good way to get that from base given the pid. These Mac
- // variants of the IsProcessBackgrounded and SetProcessBackgrounded API take
- // the Mach port for this reason. See crbug.com/460102
- //
- // A process is backgrounded when its priority is lower than normal.
- // Return true if the process with mach port |task_port| is backgrounded,
- // false otherwise.
- bool IsProcessBackgrounded(mach_port_t task_port) const;
-
- // Set the process with the specified mach port as backgrounded. If value is
- // true, the priority of the process will be lowered. If value is false, the
- // priority of the process will be made "normal" - equivalent to default
- // process priority. Returns true if the priority was changed, false
- // otherwise.
- bool SetProcessBackgrounded(mach_port_t task_port, bool value);
-#else
// A process is backgrounded when it's priority is lower than normal.
// Return true if this process is backgrounded, false otherwise.
bool IsProcessBackgrounded() const;
@@ -138,7 +120,7 @@ class BASE_EXPORT Process {
// will be made "normal" - equivalent to default process priority.
// Returns true if the priority was changed, false otherwise.
bool SetProcessBackgrounded(bool value);
-#endif // defined(OS_MACOSX)
+
// Returns an integer representing the priority of a process. The meaning
// of this value is OS dependent.
int GetPriority() const;
diff --git a/chromium/base/process/process_info_linux.cc b/chromium/base/process/process_info_linux.cc
index 9ec23135bfc..88ae5a137d6 100644
--- a/chromium/base/process/process_info_linux.cc
+++ b/chromium/base/process/process_info_linux.cc
@@ -12,7 +12,7 @@
namespace base {
-//static
+// static
const Time CurrentProcessInfo::CreationTime() {
ProcessHandle pid = GetCurrentProcessHandle();
int64 start_ticks =
diff --git a/chromium/base/process/process_info_mac.cc b/chromium/base/process/process_info_mac.cc
index b7cfdceda05..7680d373df3 100644
--- a/chromium/base/process/process_info_mac.cc
+++ b/chromium/base/process/process_info_mac.cc
@@ -14,7 +14,7 @@
namespace base {
-//static
+// static
const Time CurrentProcessInfo::CreationTime() {
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
size_t len = 0;
diff --git a/chromium/base/process/process_iterator_mac.cc b/chromium/base/process/process_iterator_mac.cc
index 9b33a0a8e40..d9136f48b03 100644
--- a/chromium/base/process/process_iterator_mac.cc
+++ b/chromium/base/process/process_iterator_mac.cc
@@ -22,7 +22,8 @@ ProcessIterator::ProcessIterator(const ProcessFilter* filter)
// but trying to find where we were in a constantly changing list is basically
// impossible.
- int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_UID, geteuid() };
+ int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_UID,
+ static_cast<int>(geteuid()) };
// Since more processes could start between when we get the size and when
// we get the list, we do a loop to keep trying until we get it.
diff --git a/chromium/base/process/process_linux.cc b/chromium/base/process/process_linux.cc
index 6e10dd2301f..958ffd6dafb 100644
--- a/chromium/base/process/process_linux.cc
+++ b/chromium/base/process/process_linux.cc
@@ -102,8 +102,8 @@ bool Process::IsProcessBackgrounded() const {
if (base::ReadFileToString(
base::FilePath(StringPrintf(kProcPath, process_)),
&proc)) {
- std::vector<std::string> proc_parts;
- base::SplitString(proc, ':', &proc_parts);
+ std::vector<std::string> proc_parts = base::SplitString(
+ proc, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
DCHECK_EQ(proc_parts.size(), 3u);
bool ret = proc_parts[2] == std::string(kBackground);
return ret;
diff --git a/chromium/base/process/process_mac.cc b/chromium/base/process/process_mac.cc
deleted file mode 100644
index 1913cc378e8..00000000000
--- a/chromium/base/process/process_mac.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2015 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.h"
-
-#include "base/mac/mac_util.h"
-#include "base/mac/mach_logging.h"
-
-#include <mach/mach.h>
-
-// The following was added to <mach/task_policy.h> after 10.8.
-// TODO(shrike): Remove the TASK_OVERRIDE_QOS_POLICY ifndef once builders
-// reach 10.9 or higher.
-#ifndef TASK_OVERRIDE_QOS_POLICY
-
-#define TASK_OVERRIDE_QOS_POLICY 9
-
-typedef struct task_category_policy task_category_policy_data_t;
-typedef struct task_category_policy* task_category_policy_t;
-
-enum task_latency_qos {
- LATENCY_QOS_TIER_UNSPECIFIED = 0x0,
- LATENCY_QOS_TIER_0 = ((0xFF << 16) | 1),
- LATENCY_QOS_TIER_1 = ((0xFF << 16) | 2),
- LATENCY_QOS_TIER_2 = ((0xFF << 16) | 3),
- LATENCY_QOS_TIER_3 = ((0xFF << 16) | 4),
- LATENCY_QOS_TIER_4 = ((0xFF << 16) | 5),
- LATENCY_QOS_TIER_5 = ((0xFF << 16) | 6)
-};
-typedef integer_t task_latency_qos_t;
-enum task_throughput_qos {
- THROUGHPUT_QOS_TIER_UNSPECIFIED = 0x0,
- THROUGHPUT_QOS_TIER_0 = ((0xFE << 16) | 1),
- THROUGHPUT_QOS_TIER_1 = ((0xFE << 16) | 2),
- THROUGHPUT_QOS_TIER_2 = ((0xFE << 16) | 3),
- THROUGHPUT_QOS_TIER_3 = ((0xFE << 16) | 4),
- THROUGHPUT_QOS_TIER_4 = ((0xFE << 16) | 5),
- THROUGHPUT_QOS_TIER_5 = ((0xFE << 16) | 6),
-};
-
-#define LATENCY_QOS_LAUNCH_DEFAULT_TIER LATENCY_QOS_TIER_3
-#define THROUGHPUT_QOS_LAUNCH_DEFAULT_TIER THROUGHPUT_QOS_TIER_3
-
-typedef integer_t task_throughput_qos_t;
-
-struct task_qos_policy {
- task_latency_qos_t task_latency_qos_tier;
- task_throughput_qos_t task_throughput_qos_tier;
-};
-
-typedef struct task_qos_policy* task_qos_policy_t;
-#define TASK_QOS_POLICY_COUNT \
- ((mach_msg_type_number_t)(sizeof(struct task_qos_policy) / sizeof(integer_t)))
-
-#endif // TASK_OVERRIDE_QOS_POLICY
-
-namespace base {
-
-bool Process::CanBackgroundProcesses() {
- return true;
-}
-
-bool Process::IsProcessBackgrounded(mach_port_t task_port) const {
- // See SetProcessBackgrounded().
- DCHECK(IsValid());
- DCHECK_NE(task_port, TASK_NULL);
-
- task_category_policy_data_t category_policy;
- mach_msg_type_number_t task_info_count = TASK_CATEGORY_POLICY_COUNT;
- boolean_t get_default = FALSE;
-
- kern_return_t result =
- task_policy_get(task_port, TASK_CATEGORY_POLICY,
- reinterpret_cast<task_policy_t>(&category_policy),
- &task_info_count, &get_default);
- MACH_LOG_IF(ERROR, result != KERN_SUCCESS, result) <<
- "task_policy_get TASK_CATEGORY_POLICY";
-
- if (result == KERN_SUCCESS && get_default == FALSE) {
- return category_policy.role == TASK_BACKGROUND_APPLICATION;
- }
- return false;
-}
-
-bool Process::SetProcessBackgrounded(mach_port_t task_port, bool background) {
- DCHECK(IsValid());
- DCHECK_NE(task_port, TASK_NULL);
-
- if (!CanBackgroundProcesses()) {
- return false;
- } else if (IsProcessBackgrounded(task_port) == background) {
- return true;
- }
-
- task_category_policy category_policy;
- category_policy.role =
- background ? TASK_BACKGROUND_APPLICATION : TASK_FOREGROUND_APPLICATION;
- kern_return_t result =
- task_policy_set(task_port, TASK_CATEGORY_POLICY,
- reinterpret_cast<task_policy_t>(&category_policy),
- TASK_CATEGORY_POLICY_COUNT);
-
- if (result != KERN_SUCCESS) {
- MACH_LOG(ERROR, result) << "task_policy_set TASK_CATEGORY_POLICY";
- return false;
- } else if (!mac::IsOSMavericksOrLater()) {
- return true;
- }
-
- // Latency QoS regulates timer throttling/accuracy. Select default tier
- // on foreground because precise timer firing isn't needed.
- struct task_qos_policy qos_policy = {
- background ? LATENCY_QOS_TIER_5 : LATENCY_QOS_TIER_UNSPECIFIED,
- background ? THROUGHPUT_QOS_TIER_5 : THROUGHPUT_QOS_TIER_UNSPECIFIED
- };
- result = task_policy_set(task_port, TASK_OVERRIDE_QOS_POLICY,
- reinterpret_cast<task_policy_t>(&qos_policy),
- TASK_QOS_POLICY_COUNT);
- if (result != KERN_SUCCESS) {
- MACH_LOG(ERROR, result) << "task_policy_set TASK_OVERRIDE_QOS_POLICY";
- return false;
- }
-
- return true;
-}
-
-} // namespace base
diff --git a/chromium/base/process/process_metrics.h b/chromium/base/process/process_metrics.h
index 8b4ec86693a..327483a42e7 100644
--- a/chromium/base/process/process_metrics.h
+++ b/chromium/base/process/process_metrics.h
@@ -19,6 +19,7 @@
#if defined(OS_MACOSX)
#include <mach/mach.h>
+#include "base/process/port_provider_mac.h"
#endif
namespace base {
@@ -101,16 +102,6 @@ class BASE_EXPORT ProcessMetrics {
#if !defined(OS_MACOSX) || defined(OS_IOS)
static ProcessMetrics* CreateProcessMetrics(ProcessHandle process);
#else
- class PortProvider {
- public:
- virtual ~PortProvider() {}
-
- // Should return the mach task for |process| if possible, or else
- // |MACH_PORT_NULL|. Only processes that this returns tasks for will have
- // metrics on OS X (except for the current process, which always gets
- // metrics).
- virtual mach_port_t TaskForPid(ProcessHandle process) const = 0;
- };
// The port provider needs to outlive the ProcessMetrics object returned by
// this function. If NULL is passed as provider, the returned object
@@ -242,23 +233,16 @@ BASE_EXPORT size_t GetMaxFds();
BASE_EXPORT void SetFdLimit(unsigned int max_descriptors);
#endif // defined(OS_POSIX)
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-// Parse the data found in /proc/<pid>/stat and return the sum of the
-// CPU-related ticks. Returns -1 on parse error.
-// Exposed for testing.
-BASE_EXPORT int ParseProcStatCPU(const std::string& input);
-
-// Get the number of threads of |process| as available in /proc/<pid>/stat.
-// This should be used with care as no synchronization with running threads is
-// done. This is mostly useful to guarantee being single-threaded.
-// Returns 0 on failure.
-BASE_EXPORT int GetNumberOfThreads(ProcessHandle process);
-
-// /proc/self/exe refers to the current executable.
-BASE_EXPORT extern const char kProcSelfExe[];
-
-// Data from /proc/meminfo about system-wide memory consumption.
-// Values are in KB.
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
+ defined(OS_ANDROID)
+// Data about system-wide memory consumption. Values are in KB. Available on
+// Windows, Mac, Linux, Android and Chrome OS.
+//
+// Total/free memory are available on all platforms that implement
+// GetSystemMemoryInfo(). Total/free swap memory are available on all platforms
+// except on Mac. Buffers/cached/active_anon/inactive_anon/active_file/
+// inactive_file/dirty/pswpin/pswpout/pgmajfault are available on
+// Linux/Android/Chrome OS. Shmem/slab/gem_objects/gem_size are Chrome OS only.
struct BASE_EXPORT SystemMemoryInfoKB {
SystemMemoryInfoKB();
@@ -267,30 +251,62 @@ struct BASE_EXPORT SystemMemoryInfoKB {
int total;
int free;
+
+#if !defined(OS_MACOSX)
+ int swap_total;
+ int swap_free;
+#endif
+
+#if defined(OS_ANDROID) || defined(OS_LINUX)
int buffers;
int cached;
int active_anon;
int inactive_anon;
int active_file;
int inactive_file;
- int swap_total;
- int swap_free;
int dirty;
// vmstats data.
int pswpin;
int pswpout;
int pgmajfault;
+#endif // defined(OS_ANDROID) || defined(OS_LINUX)
-#ifdef OS_CHROMEOS
+#if defined(OS_CHROMEOS)
int shmem;
int slab;
// Gem data will be -1 if not supported.
int gem_objects;
long long gem_size;
-#endif
+#endif // defined(OS_CHROMEOS)
};
+// On Linux/Android/Chrome OS, system-wide memory consumption data is parsed
+// from /proc/meminfo and /proc/vmstat. On Windows/Mac, it is obtained using
+// system API calls.
+//
+// Fills in the provided |meminfo| structure. Returns true on success.
+// Exposed for memory debugging widget.
+BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo);
+
+#endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) ||
+ // defined(OS_ANDROID)
+
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+// Parse the data found in /proc/<pid>/stat and return the sum of the
+// CPU-related ticks. Returns -1 on parse error.
+// Exposed for testing.
+BASE_EXPORT int ParseProcStatCPU(const std::string& input);
+
+// Get the number of threads of |process| as available in /proc/<pid>/stat.
+// This should be used with care as no synchronization with running threads is
+// done. This is mostly useful to guarantee being single-threaded.
+// Returns 0 on failure.
+BASE_EXPORT int GetNumberOfThreads(ProcessHandle process);
+
+// /proc/self/exe refers to the current executable.
+BASE_EXPORT extern const char kProcSelfExe[];
+
// 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,
@@ -301,12 +317,6 @@ BASE_EXPORT bool ParseProcMeminfo(const std::string& input,
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.
-// Exposed for memory debugging widget.
-BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo);
-
// Data from /proc/diskstats about system-wide disk I/O.
struct BASE_EXPORT SystemDiskInfo {
SystemDiskInfo();
diff --git a/chromium/base/process/process_metrics_ios.cc b/chromium/base/process/process_metrics_ios.cc
index 07f2c8de1d4..135ef43c06c 100644
--- a/chromium/base/process/process_metrics_ios.cc
+++ b/chromium/base/process/process_metrics_ios.cc
@@ -23,6 +23,11 @@ bool GetTaskInfo(task_basic_info_64* task_info_data) {
} // namespace
+SystemMemoryInfoKB::SystemMemoryInfoKB() {
+ total = 0;
+ free = 0;
+}
+
ProcessMetrics::ProcessMetrics(ProcessHandle process) {}
ProcessMetrics::~ProcessMetrics() {}
@@ -82,4 +87,11 @@ size_t GetSystemCommitCharge() {
return 0;
}
+// Bytes committed by the system.
+bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
+ // Unimplemented. Must enable unittest for IOS when this gets implemented.
+ NOTIMPLEMENTED();
+ return false;
+}
+
} // namespace base
diff --git a/chromium/base/process/process_metrics_linux.cc b/chromium/base/process/process_metrics_linux.cc
index 47a79e51e5e..adca7c5ee23 100644
--- a/chromium/base/process/process_metrics_linux.cc
+++ b/chromium/base/process/process_metrics_linux.cc
@@ -67,8 +67,8 @@ size_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) {
const std::string& key = pairs[i].first;
const std::string& value_str = pairs[i].second;
if (key == field) {
- std::vector<std::string> split_value_str;
- SplitString(value_str, ' ', &split_value_str);
+ std::vector<StringPiece> split_value_str = SplitStringPiece(
+ value_str, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
if (split_value_str.size() != 2 || split_value_str[1] != "kB") {
NOTREACHED();
return 0;
@@ -316,8 +316,9 @@ bool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage)
return false;
}
- std::vector<std::string> totmaps_fields;
- SplitStringAlongWhitespace(totmaps_data, &totmaps_fields);
+ std::vector<std::string> totmaps_fields = SplitString(
+ totmaps_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY);
DCHECK_EQ("Pss:", totmaps_fields[kPssIndex-1]);
DCHECK_EQ("Private_Clean:", totmaps_fields[kPrivate_CleanIndex - 1]);
@@ -368,8 +369,8 @@ bool ProcessMetrics::GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage)
return false;
}
- std::vector<std::string> statm_vec;
- SplitString(statm, ' ', &statm_vec);
+ std::vector<StringPiece> statm_vec = SplitStringPiece(
+ statm, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
if (statm_vec.size() != 7)
return false; // Not the format we expect.
diff --git a/chromium/base/process/process_metrics_mac.cc b/chromium/base/process/process_metrics_mac.cc
index f84b435a109..a2ecd8e7185 100644
--- a/chromium/base/process/process_metrics_mac.cc
+++ b/chromium/base/process/process_metrics_mac.cc
@@ -77,6 +77,11 @@ bool IsAddressInSharedRegion(mach_vm_address_t addr, cpu_type_t type) {
} // namespace
+SystemMemoryInfoKB::SystemMemoryInfoKB() {
+ total = 0;
+ free = 0;
+}
+
// Getting a mach task from a pid for another process requires permissions in
// general, so there doesn't really seem to be a way to do these (and spinning
// up ps to fetch each stats seems dangerous to put in a base api for anyone to
@@ -86,7 +91,7 @@ bool IsAddressInSharedRegion(mach_vm_address_t addr, cpu_type_t type) {
// static
ProcessMetrics* ProcessMetrics::CreateProcessMetrics(
ProcessHandle process,
- ProcessMetrics::PortProvider* port_provider) {
+ PortProvider* port_provider) {
return new ProcessMetrics(process, port_provider);
}
@@ -325,7 +330,7 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
}
ProcessMetrics::ProcessMetrics(ProcessHandle process,
- ProcessMetrics::PortProvider* port_provider)
+ PortProvider* port_provider)
: process_(process),
last_system_time_(0),
last_absolute_idle_wakeups_(0),
@@ -358,4 +363,32 @@ size_t GetSystemCommitCharge() {
return (data.active_count * PAGE_SIZE) / 1024;
}
+// On Mac, We only get total memory and free memory from the system.
+bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
+ struct host_basic_info hostinfo;
+ mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
+ base::mac::ScopedMachSendRight host(mach_host_self());
+ int result = host_info(host, HOST_BASIC_INFO,
+ reinterpret_cast<host_info_t>(&hostinfo), &count);
+ if (result != KERN_SUCCESS)
+ return false;
+
+ DCHECK_EQ(HOST_BASIC_INFO_COUNT, count);
+ meminfo->total = static_cast<int>(hostinfo.max_mem / 1024);
+
+ vm_statistics_data_t vm_info;
+ count = HOST_VM_INFO_COUNT;
+
+ if (host_statistics(host.get(), HOST_VM_INFO,
+ reinterpret_cast<host_info_t>(&vm_info),
+ &count) != KERN_SUCCESS) {
+ return false;
+ }
+
+ meminfo->free = static_cast<int>(
+ (vm_info.free_count - vm_info.speculative_count) * PAGE_SIZE / 1024);
+
+ return true;
+}
+
} // namespace base
diff --git a/chromium/base/process/process_metrics_unittest.cc b/chromium/base/process/process_metrics_unittest.cc
index 76767b09a95..31479cefff6 100644
--- a/chromium/base/process/process_metrics_unittest.cc
+++ b/chromium/base/process/process_metrics_unittest.cc
@@ -270,7 +270,8 @@ TEST_F(SystemMetricsTest, ParseVmstat) {
}
#endif // defined(OS_LINUX) || defined(OS_ANDROID)
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) || \
+ defined(OS_LINUX) || defined(OS_ANDROID)
TEST(SystemMetrics2Test, GetSystemMemoryInfo) {
base::SystemMemoryInfoKB info;
EXPECT_TRUE(base::GetSystemMemoryInfo(&info));
@@ -278,21 +279,25 @@ TEST(SystemMetrics2Test, GetSystemMemoryInfo) {
// Ensure each field received a value.
EXPECT_GT(info.total, 0);
EXPECT_GT(info.free, 0);
+#if defined(OS_LINUX) || defined(OS_ANDROID)
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);
+#endif // defined(OS_LINUX) || defined(OS_ANDROID)
// All the values should be less than the total amount of memory.
EXPECT_LT(info.free, info.total);
+#if defined(OS_LINUX) || defined(OS_ANDROID)
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);
+#endif // defined(OS_LINUX) || defined(OS_ANDROID)
#if defined(OS_CHROMEOS)
// Chrome OS exposes shmem.
@@ -302,7 +307,8 @@ TEST(SystemMetrics2Test, GetSystemMemoryInfo) {
// and gem_size cannot be tested here.
#endif
}
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
+#endif // defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) ||
+ // defined(OS_LINUX) || defined(OS_ANDROID)
#if defined(OS_LINUX) || defined(OS_ANDROID)
TEST(ProcessMetricsTest, ParseProcStatCPU) {
diff --git a/chromium/base/process/process_metrics_win.cc b/chromium/base/process/process_metrics_win.cc
index 170f6dcaab8..c3b3e50ff61 100644
--- a/chromium/base/process/process_metrics_win.cc
+++ b/chromium/base/process/process_metrics_win.cc
@@ -6,15 +6,32 @@
#include <windows.h>
#include <psapi.h>
+#include <winternl.h>
#include "base/logging.h"
#include "base/sys_info.h"
namespace base {
+namespace {
// System pagesize. This value remains constant on x86/64 architectures.
const int PAGESIZE_KB = 4;
+typedef NTSTATUS(WINAPI* NTQUERYSYSTEMINFORMATION)(
+ SYSTEM_INFORMATION_CLASS SystemInformationClass,
+ PVOID SystemInformation,
+ ULONG SystemInformationLength,
+ PULONG ReturnLength);
+
+} // namespace
+
+SystemMemoryInfoKB::SystemMemoryInfoKB() {
+ total = 0;
+ free = 0;
+ swap_total = 0;
+ swap_free = 0;
+}
+
ProcessMetrics::~ProcessMetrics() { }
// static
@@ -285,4 +302,24 @@ size_t GetPageSize() {
return PAGESIZE_KB * 1024;
}
+// This function uses the following mapping between MEMORYSTATUSEX and
+// SystemMemoryInfoKB:
+// ullTotalPhys ==> total
+// ullAvailPhys ==> free
+// ullTotalPageFile ==> swap_total
+// ullAvailPageFile ==> swap_free
+bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
+ MEMORYSTATUSEX mem_status;
+ mem_status.dwLength = sizeof(mem_status);
+ if (!::GlobalMemoryStatusEx(&mem_status))
+ return false;
+
+ meminfo->total = mem_status.ullTotalPhys / 1024;
+ meminfo->free = mem_status.ullAvailPhys / 1024;
+ meminfo->swap_total = mem_status.ullTotalPageFile / 1024;
+ meminfo->swap_free = mem_status.ullAvailPageFile / 1024;
+
+ return true;
+}
+
} // namespace base
diff --git a/chromium/base/process/process_posix.cc b/chromium/base/process/process_posix.cc
index b6f22c1edcf..72e49faefca 100644
--- a/chromium/base/process/process_posix.cc
+++ b/chromium/base/process/process_posix.cc
@@ -255,12 +255,12 @@ Process Process::DeprecatedGetProcessFromHandle(ProcessHandle handle) {
return Process(handle);
}
-#if !defined(OS_LINUX) && !defined(OS_MACOSX)
+#if !defined(OS_LINUX)
// static
bool Process::CanBackgroundProcesses() {
return false;
}
-#endif // !defined(OS_LINUX) && !defined(OS_MACOSX)
+#endif // !defined(OS_LINUX)
bool Process::IsValid() const {
return process_ != kNullProcessHandle;
@@ -356,7 +356,7 @@ bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) {
return WaitForExitWithTimeoutImpl(Handle(), exit_code, timeout);
}
-#if !defined(OS_LINUX) && !defined(OS_MACOSX)
+#if !defined(OS_LINUX)
bool Process::IsProcessBackgrounded() const {
// See SetProcessBackgrounded().
DCHECK(IsValid());
@@ -364,13 +364,13 @@ bool Process::IsProcessBackgrounded() const {
}
bool Process::SetProcessBackgrounded(bool value) {
- // Not implemented for POSIX systems other than Mac and Linux. With POSIX, if
- // we were to lower the process priority we wouldn't be able to raise it back
- // to its initial priority.
+ // Not implemented for POSIX systems other than Linux. With POSIX, if we were
+ // to lower the process priority we wouldn't be able to raise it back to its
+ // initial priority.
NOTIMPLEMENTED();
return false;
}
-#endif // !defined(OS_LINUX) && !defined(OS_MACOSX)
+#endif // !defined(OS_LINUX)
int Process::GetPriority() const {
DCHECK(IsValid());
diff --git a/chromium/base/process/process_unittest.cc b/chromium/base/process/process_unittest.cc
index e094c032f3b..9fdc2f1e028 100644
--- a/chromium/base/process/process_unittest.cc
+++ b/chromium/base/process/process_unittest.cc
@@ -11,10 +11,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
-#if defined(OS_MACOSX)
-#include <mach/mach.h>
-#endif // OS_MACOSX
-
namespace {
#if defined(OS_WIN)
@@ -174,26 +170,16 @@ TEST_F(ProcessTest, WaitForExitWithTimeout) {
TEST_F(ProcessTest, SetProcessBackgrounded) {
Process process(SpawnChild("SimpleChildProcess"));
int old_priority = process.GetPriority();
-#if defined(OS_MACOSX)
- // On the Mac, backgrounding a process requires a port to that process.
- // In the browser it's available through the MachBroker class, which is not
- // part of base. Additionally, there is an indefinite amount of time between
- // spawning a process and receiving its port. Because this test just checks
- // the ability to background/foreground a process, we can use the current
- // process's port instead.
- mach_port_t process_port = mach_task_self();
- EXPECT_TRUE(process.SetProcessBackgrounded(process_port, true));
- EXPECT_TRUE(process.IsProcessBackgrounded(process_port));
- EXPECT_TRUE(process.SetProcessBackgrounded(process_port, false));
- EXPECT_FALSE(process.IsProcessBackgrounded(process_port));
-#elif defined(OS_WIN)
+#if defined(OS_WIN)
EXPECT_TRUE(process.SetProcessBackgrounded(true));
EXPECT_TRUE(process.IsProcessBackgrounded());
EXPECT_TRUE(process.SetProcessBackgrounded(false));
EXPECT_FALSE(process.IsProcessBackgrounded());
#else
- process.SetProcessBackgrounded(true);
- process.SetProcessBackgrounded(false);
+ if (process.CanBackgroundProcesses()) {
+ process.SetProcessBackgrounded(true);
+ process.SetProcessBackgrounded(false);
+ }
#endif
int new_priority = process.GetPriority();
EXPECT_EQ(old_priority, new_priority);
@@ -204,13 +190,7 @@ TEST_F(ProcessTest, SetProcessBackgrounded) {
TEST_F(ProcessTest, SetProcessBackgroundedSelf) {
Process process = Process::Current();
int old_priority = process.GetPriority();
-#if defined(OS_MACOSX)
- mach_port_t process_port = mach_task_self();
- EXPECT_TRUE(process.SetProcessBackgrounded(process_port, true));
- EXPECT_TRUE(process.IsProcessBackgrounded(process_port));
- EXPECT_TRUE(process.SetProcessBackgrounded(process_port, false));
- EXPECT_FALSE(process.IsProcessBackgrounded(process_port));
-#elif defined(OS_WIN)
+#if defined(OS_WIN)
EXPECT_TRUE(process.SetProcessBackgrounded(true));
EXPECT_TRUE(process.IsProcessBackgrounded());
EXPECT_TRUE(process.SetProcessBackgrounded(false));
diff --git a/chromium/base/process/process_util_unittest.cc b/chromium/base/process/process_util_unittest.cc
index 6c1a3f1d761..08144f2a18e 100644
--- a/chromium/base/process/process_util_unittest.cc
+++ b/chromium/base/process/process_util_unittest.cc
@@ -59,6 +59,9 @@
#include <malloc/malloc.h>
#include "base/mac/mac_util.h"
#endif
+#if defined(OS_ANDROID)
+#include "third_party/lss/linux_syscall_support.h"
+#endif
using base::FilePath;
@@ -75,7 +78,7 @@ const char kShellPath[] = "/system/bin/sh";
const char kPosixShell[] = "sh";
#else
const char kShellPath[] = "/bin/sh";
-const char kPosixShell[] = "bash";
+const char kPosixShell[] = "sh";
#endif
#endif // defined(OS_POSIX)
@@ -226,7 +229,19 @@ const char kSignalFileCrash[] = "CrashingChildProcess.die";
MULTIPROCESS_TEST_MAIN(CrashingChildProcess) {
WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileCrash).c_str());
-#if defined(OS_POSIX)
+#if defined(OS_ANDROID)
+ // Android L+ expose signal and sigaction symbols that override the system
+ // ones. There is a bug in these functions where a request to set the handler
+ // to SIG_DFL is ignored. In that case, an infinite loop is entered as the
+ // signal is repeatedly sent to the crash dump signal handler.
+ // To work around this, directly call the system's sigaction.
+ struct kernel_sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sys_sigemptyset(&sa.sa_mask);
+ sa.sa_handler_ = SIG_DFL;
+ sa.sa_flags = SA_RESTART;
+ sys_rt_sigaction(SIGSEGV, &sa, NULL, sizeof(kernel_sigset_t));
+#elif defined(OS_POSIX)
// Have to disable to signal handler for segv so we can get a crash
// instead of an abnormal termination through the crash dump handler.
::signal(SIGSEGV, SIG_DFL);
diff --git a/chromium/base/process/process_win.cc b/chromium/base/process/process_win.cc
index 30cd9dc7372..818864fa528 100644
--- a/chromium/base/process/process_win.cc
+++ b/chromium/base/process/process_win.cc
@@ -6,10 +6,8 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
-#include "base/metrics/field_trial.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/kill.h"
-#include "base/strings/string_util.h"
#include "base/win/windows_version.h"
namespace {
@@ -179,23 +177,7 @@ bool Process::SetProcessBackgrounded(bool value) {
priority = value ? PROCESS_MODE_BACKGROUND_BEGIN :
PROCESS_MODE_BACKGROUND_END;
} else {
- // Experiment (http://crbug.com/458594) with using IDLE_PRIORITY_CLASS as a
- // background priority for background renderers (this code path is
- // technically for more than just the renderers but they're the only use
- // case in practice and experimenting here direclty is thus easier -- plus
- // it doesn't really hurt as above we already state our intent of using
- // PROCESS_MODE_BACKGROUND_BEGIN if available which is essentially
- // IDLE_PRIORITY_CLASS plus lowered IO priority). Enabled by default in the
- // asbence of field trials to get coverage on the perf waterfall.
- DWORD background_priority = IDLE_PRIORITY_CLASS;
- base::FieldTrial* trial =
- base::FieldTrialList::Find("BackgroundRendererProcesses");
- if (trial && StartsWith(trial->group_name(), "AllowBelowNormalFromBrowser",
- CompareCase::SENSITIVE)) {
- background_priority = BELOW_NORMAL_PRIORITY_CLASS;
- }
-
- priority = value ? background_priority : NORMAL_PRIORITY_CLASS;
+ priority = value ? IDLE_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS;
}
return (::SetPriorityClass(Handle(), priority) != 0);