summaryrefslogtreecommitdiffstats
path: root/chromium/base/process
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-01-04 14:17:57 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-01-05 10:05:06 +0000
commit39d357e3248f80abea0159765ff39554affb40db (patch)
treeaba0e6bfb76de0244bba0f5fdbd64b830dd6e621 /chromium/base/process
parent87778abf5a1f89266f37d1321b92a21851d8244d (diff)
BASELINE: Update Chromium to 55.0.2883.105
And updates ninja to 1.7.2 Change-Id: I20d43c737f82764d857ada9a55586901b18b9243 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/base/process')
-rw-r--r--chromium/base/process/internal_linux.cc26
-rw-r--r--chromium/base/process/internal_linux.h3
-rw-r--r--chromium/base/process/kill.h11
-rw-r--r--chromium/base/process/kill_posix.cc2
-rw-r--r--chromium/base/process/kill_win.cc7
-rw-r--r--chromium/base/process/launch.cc36
-rw-r--r--chromium/base/process/launch.h53
-rw-r--r--chromium/base/process/launch_posix.cc113
-rw-r--r--chromium/base/process/launch_win.cc9
-rw-r--r--chromium/base/process/memory.cc5
-rw-r--r--chromium/base/process/memory.h14
-rw-r--r--chromium/base/process/memory_mac.mm2
-rw-r--r--chromium/base/process/memory_stubs.cc4
-rw-r--r--chromium/base/process/memory_unittest.cc106
-rw-r--r--chromium/base/process/memory_win.cc21
-rw-r--r--chromium/base/process/process_metrics.cc2
-rw-r--r--chromium/base/process/process_metrics.h22
-rw-r--r--chromium/base/process/process_metrics_freebsd.cc11
-rw-r--r--chromium/base/process/process_metrics_ios.cc11
-rw-r--r--chromium/base/process/process_metrics_linux.cc31
-rw-r--r--chromium/base/process/process_metrics_mac.cc12
-rw-r--r--chromium/base/process/process_metrics_openbsd.cc16
-rw-r--r--chromium/base/process/process_metrics_posix.cc2
-rw-r--r--chromium/base/process/process_metrics_unittest.cc14
-rw-r--r--chromium/base/process/process_metrics_win.cc106
-rw-r--r--chromium/base/process/process_posix.cc4
-rw-r--r--chromium/base/process/process_util_unittest.cc117
-rw-r--r--chromium/base/process/process_win.cc4
28 files changed, 322 insertions, 442 deletions
diff --git a/chromium/base/process/internal_linux.cc b/chromium/base/process/internal_linux.cc
index d286f4e7539..e9ed641dc02 100644
--- a/chromium/base/process/internal_linux.cc
+++ b/chromium/base/process/internal_linux.cc
@@ -170,6 +170,32 @@ Time GetBootTime() {
return Time::FromTimeT(btime);
}
+TimeDelta GetUserCpuTimeSinceBoot() {
+ FilePath path("/proc/stat");
+ std::string contents;
+ if (!ReadProcFile(path, &contents))
+ return TimeDelta();
+
+ ProcStatMap proc_stat;
+ ParseProcStat(contents, &proc_stat);
+ ProcStatMap::const_iterator cpu_it = proc_stat.find("cpu");
+ if (cpu_it == proc_stat.end())
+ return TimeDelta();
+
+ std::vector<std::string> cpu = SplitString(
+ cpu_it->second, kWhitespaceASCII, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
+
+ if (cpu.size() < 2 || cpu[0] != "cpu")
+ return TimeDelta();
+
+ uint64_t user;
+ uint64_t nice;
+ if (!StringToUint64(cpu[0], &user) || !StringToUint64(cpu[1], &nice))
+ return TimeDelta();
+
+ return ClockTicksToTimeDelta(user + nice);
+}
+
TimeDelta ClockTicksToTimeDelta(int clock_ticks) {
// This queries the /proc-specific scaling factor which is
// conceptually the system hertz. To dump this value on another
diff --git a/chromium/base/process/internal_linux.h b/chromium/base/process/internal_linux.h
index ba793f7cc7c..b36f75a90af 100644
--- a/chromium/base/process/internal_linux.h
+++ b/chromium/base/process/internal_linux.h
@@ -83,6 +83,9 @@ size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid,
// Returns the time that the OS started. Clock ticks are relative to this.
Time GetBootTime();
+// Returns the amount of time spent in user space since boot across all CPUs.
+TimeDelta GetUserCpuTimeSinceBoot();
+
// Converts Linux clock ticks to a wall time delta.
TimeDelta ClockTicksToTimeDelta(int clock_ticks);
diff --git a/chromium/base/process/kill.h b/chromium/base/process/kill.h
index c664f33262f..6d410e02a0d 100644
--- a/chromium/base/process/kill.h
+++ b/chromium/base/process/kill.h
@@ -18,6 +18,16 @@ namespace base {
class ProcessFilter;
+#if defined(OS_WIN)
+namespace win {
+
+// See definition in sandbox/win/src/sandbox_types.h
+const DWORD kSandboxFatalMemoryExceeded = 7012;
+
+} // namespace win
+
+#endif // OS_WIN
+
// Return status values from GetTerminationStatus. Don't use these as
// exit code arguments to KillProcess*(), use platform/application
// specific values instead.
@@ -39,6 +49,7 @@ enum TerminationStatus {
TERMINATION_STATUS_OOM_PROTECTED, // child was protected from oom kill
#endif
TERMINATION_STATUS_LAUNCH_FAILED, // child process never launched
+ TERMINATION_STATUS_OOM, // Process died due to oom
TERMINATION_STATUS_MAX_ENUM
};
diff --git a/chromium/base/process/kill_posix.cc b/chromium/base/process/kill_posix.cc
index 85470e05f97..4dc60ef2a24 100644
--- a/chromium/base/process/kill_posix.cc
+++ b/chromium/base/process/kill_posix.cc
@@ -52,6 +52,8 @@ TerminationStatus GetTerminationStatusImpl(ProcessHandle handle,
case SIGFPE:
case SIGILL:
case SIGSEGV:
+ case SIGTRAP:
+ case SIGSYS:
return TERMINATION_STATUS_PROCESS_CRASHED;
case SIGKILL:
#if defined(OS_CHROMEOS)
diff --git a/chromium/base/process/kill_win.cc b/chromium/base/process/kill_win.cc
index 358590e7a38..ecb08421cfa 100644
--- a/chromium/base/process/kill_win.cc
+++ b/chromium/base/process/kill_win.cc
@@ -8,12 +8,14 @@
#include <io.h>
#include <stdint.h>
+#include <algorithm>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/process/memory.h"
#include "base/process/process_iterator.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/win/object_watcher.h"
@@ -146,6 +148,11 @@ TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
case kDebuggerTerminatedExitCode: // Debugger terminated process.
case kProcessKilledExitCode: // Task manager kill.
return TERMINATION_STATUS_PROCESS_WAS_KILLED;
+ case base::win::kSandboxFatalMemoryExceeded: // Terminated process due to
+ // exceeding the sandbox job
+ // object memory limits.
+ case base::win::kOomExceptionCode: // Ran out of memory.
+ return TERMINATION_STATUS_OOM;
default:
// All other exit codes indicate crashes.
return TERMINATION_STATUS_PROCESS_CRASHED;
diff --git a/chromium/base/process/launch.cc b/chromium/base/process/launch.cc
index 3ca5155a122..c03e1a75db1 100644
--- a/chromium/base/process/launch.cc
+++ b/chromium/base/process/launch.cc
@@ -7,43 +7,11 @@
namespace base {
-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),
- job_handle(NULL),
- stdin_handle(NULL),
- stdout_handle(NULL),
- stderr_handle(NULL),
- force_breakaway_from_job_(false)
-#else
- clear_environ(false),
- fds_to_remap(NULL),
- maximize_rlimits(NULL),
- new_process_group(false)
-#if defined(OS_LINUX)
- , clone_flags(0)
- , allow_new_privs(false)
- , kill_on_parent_death(false)
-#endif // OS_LINUX
-#if defined(OS_POSIX)
- , pre_exec_delegate(NULL)
-#endif // OS_POSIX
-#if defined(OS_CHROMEOS)
- , ctrl_terminal_fd(-1)
-#endif // OS_CHROMEOS
-#endif // !defined(OS_WIN)
- {
-}
+LaunchOptions::LaunchOptions() = default;
LaunchOptions::LaunchOptions(const LaunchOptions& other) = default;
-LaunchOptions::~LaunchOptions() {
-}
+LaunchOptions::~LaunchOptions() = default;
LaunchOptions LaunchOptionsForTest() {
LaunchOptions options;
diff --git a/chromium/base/process/launch.h b/chromium/base/process/launch.h
index 28cea7b931c..2b2040c7d42 100644
--- a/chromium/base/process/launch.h
+++ b/chromium/base/process/launch.h
@@ -63,17 +63,17 @@ struct BASE_EXPORT LaunchOptions {
~LaunchOptions();
// If true, wait for the process to complete.
- bool wait;
+ bool wait = false;
// If not empty, change to this directory before executing the new process.
base::FilePath current_directory;
#if defined(OS_WIN)
- bool start_hidden;
+ bool start_hidden = false;
// If non-null, inherit exactly the list of handles in this vector (these
// handles must be inheritable).
- HandlesToInheritVector* handles_to_inherit;
+ HandlesToInheritVector* handles_to_inherit = nullptr;
// If true, the new process inherits handles from the parent. In production
// code this flag should be used only when running short-lived, trusted
@@ -81,7 +81,7 @@ struct BASE_EXPORT LaunchOptions {
// 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.
- bool inherit_handles;
+ bool inherit_handles = false;
// 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
@@ -90,29 +90,29 @@ struct BASE_EXPORT LaunchOptions {
// To avoid hard to diagnose problems, when specified this loads the
// environment variables associated with the user and if this operation fails
// the entire call fails as well.
- UserTokenHandle as_user;
+ UserTokenHandle as_user = nullptr;
// If true, use an empty string for the desktop name.
- bool empty_desktop_name;
+ bool empty_desktop_name = false;
// 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;
+ HANDLE job_handle = nullptr;
// Handles for the redirection of stdin, stdout and stderr. The handles must
// be inheritable. Caller should either set all three of them or none (i.e.
// there is no way to redirect stderr without redirecting stdin). The
// |inherit_handles| flag must be set to true when redirecting stdio stream.
- HANDLE stdin_handle;
- HANDLE stdout_handle;
- HANDLE stderr_handle;
+ HANDLE stdin_handle = nullptr;
+ HANDLE stdout_handle = nullptr;
+ HANDLE stderr_handle = nullptr;
// If set to true, ensures that the child process is launched with the
// CREATE_BREAKAWAY_FROM_JOB flag which allows it to breakout of the parent
// job if any.
- bool force_breakaway_from_job_;
-#else
+ bool force_breakaway_from_job_ = false;
+#else // !defined(OS_WIN)
// Set/unset environment variables. These are applied on top of the parent
// process environment. Empty (the default) means to inherit the same
// environment. See AlterEnvironment().
@@ -120,53 +120,58 @@ struct BASE_EXPORT LaunchOptions {
// Clear the environment for the new process before processing changes from
// |environ|.
- bool clear_environ;
+ bool clear_environ = false;
// 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().
- const FileHandleMappingVector* fds_to_remap;
+ const FileHandleMappingVector* fds_to_remap = nullptr;
// Each element is an RLIMIT_* constant that should be raised to its
// rlim_max. This pointer is owned by the caller and must live through
// the call to LaunchProcess().
- const std::vector<int>* maximize_rlimits;
+ const std::vector<int>* maximize_rlimits = nullptr;
// If true, start the process in a new process group, instead of
// inheriting the parent's process group. The pgid of the child process
// will be the same as its pid.
- bool new_process_group;
+ bool new_process_group = false;
#if defined(OS_LINUX)
// If non-zero, start the process using clone(), using flags as provided.
// Unlike in clone, clone_flags may not contain a custom termination signal
// that is sent to the parent when the child dies. The termination signal will
// always be set to SIGCHLD.
- int clone_flags;
+ int clone_flags = 0;
// By default, child processes will have the PR_SET_NO_NEW_PRIVS bit set. If
// true, then this bit will not be set in the new child process.
- bool allow_new_privs;
+ bool allow_new_privs = false;
// Sets parent process death signal to SIGKILL.
- bool kill_on_parent_death;
+ bool kill_on_parent_death = false;
#endif // defined(OS_LINUX)
#if defined(OS_POSIX)
+ // If not empty, launch the specified executable instead of
+ // cmdline.GetProgram(). This is useful when it is necessary to pass a custom
+ // argv[0].
+ base::FilePath real_path;
+
// If non-null, a delegate to be run immediately prior to executing the new
// program in the child process.
//
// WARNING: If LaunchProcess is called in the presence of multiple threads,
// code running in this delegate essentially needs to be async-signal safe
// (see man 7 signal for a list of allowed functions).
- PreExecDelegate* pre_exec_delegate;
+ PreExecDelegate* pre_exec_delegate = nullptr;
#endif // defined(OS_POSIX)
#if defined(OS_CHROMEOS)
// If non-negative, the specified file descriptor will be set as the launched
// process' controlling terminal.
- int ctrl_terminal_fd;
+ int ctrl_terminal_fd = -1;
#endif // defined(OS_CHROMEOS)
#endif // !defined(OS_WIN)
};
@@ -257,12 +262,6 @@ BASE_EXPORT bool GetAppOutput(const StringPiece16& cl, std::string* output);
BASE_EXPORT bool GetAppOutput(const std::vector<std::string>& argv,
std::string* output);
-// A restricted version of |GetAppOutput()| which (a) clears the environment,
-// and (b) stores at most |max_output| bytes; also, it doesn't search the path
-// for the command.
-BASE_EXPORT bool GetAppOutputRestricted(const CommandLine& cl,
- std::string* output, size_t max_output);
-
// A version of |GetAppOutput()| which also returns the exit code of the
// executed command. Returns true if the application runs and exits cleanly. If
// this is the case the exit code of the application is available in
diff --git a/chromium/base/process/launch_posix.cc b/chromium/base/process/launch_posix.cc
index 99582f59cfc..e4560436251 100644
--- a/chromium/base/process/launch_posix.cc
+++ b/chromium/base/process/launch_posix.cc
@@ -152,12 +152,12 @@ int sys_rt_sigaction(int sig, const struct kernel_sigaction* act,
// This function is intended to be used in between fork() and execve() and will
// reset all signal handlers to the default.
// The motivation for going through all of them is that sa_restorer can leak
-// from parents and help defeat ASLR on buggy kernels. We reset it to NULL.
+// from parents and help defeat ASLR on buggy kernels. We reset it to null.
// See crbug.com/177956.
void ResetChildSignalHandlersToDefaults(void) {
for (int signum = 1; ; ++signum) {
struct kernel_sigaction act = {0};
- int sigaction_get_ret = sys_rt_sigaction(signum, NULL, &act);
+ int sigaction_get_ret = sys_rt_sigaction(signum, nullptr, &act);
if (sigaction_get_ret && errno == EINVAL) {
#if !defined(NDEBUG)
// Linux supports 32 real-time signals from 33 to 64.
@@ -176,14 +176,14 @@ void ResetChildSignalHandlersToDefaults(void) {
// The kernel won't allow to re-set SIGKILL or SIGSTOP.
if (signum != SIGSTOP && signum != SIGKILL) {
act.k_sa_handler = reinterpret_cast<void*>(SIG_DFL);
- act.k_sa_restorer = NULL;
- if (sys_rt_sigaction(signum, &act, NULL)) {
+ act.k_sa_restorer = nullptr;
+ if (sys_rt_sigaction(signum, &act, nullptr)) {
RAW_LOG(FATAL, "sigaction (set) failed.");
}
}
#if !defined(NDEBUG)
// Now ask the kernel again and check that no restorer will leak.
- if (sys_rt_sigaction(signum, NULL, &act) || act.k_sa_restorer) {
+ if (sys_rt_sigaction(signum, nullptr, &act) || act.k_sa_restorer) {
RAW_LOG(FATAL, "Cound not fix sa_restorer.");
}
#endif // !defined(NDEBUG)
@@ -305,10 +305,10 @@ Process LaunchProcess(const std::vector<std::string>& argv,
for (size_t i = 0; i < argv.size(); i++) {
argv_cstr[i] = const_cast<char*>(argv[i].c_str());
}
- argv_cstr[argv.size()] = NULL;
+ argv_cstr[argv.size()] = nullptr;
std::unique_ptr<char* []> new_environ;
- char* const empty_environ = NULL;
+ char* const empty_environ = nullptr;
char* const* old_environ = GetEnvironment();
if (options.clear_environ)
old_environ = &empty_environ;
@@ -430,7 +430,7 @@ Process LaunchProcess(const std::vector<std::string>& argv,
// Set process' controlling terminal.
if (HANDLE_EINTR(setsid()) != -1) {
if (HANDLE_EINTR(
- ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) {
+ ioctl(options.ctrl_terminal_fd, TIOCSCTTY, nullptr)) == -1) {
RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set");
}
} else {
@@ -487,7 +487,10 @@ Process LaunchProcess(const std::vector<std::string>& argv,
options.pre_exec_delegate->RunAsyncSafe();
}
- execvp(argv_cstr[0], argv_cstr.get());
+ const char* executable_path = !options.real_path.empty() ?
+ options.real_path.value().c_str() : argv_cstr[0];
+
+ execvp(executable_path, argv_cstr.get());
RAW_LOG(ERROR, "LaunchProcess: failed to execvp:");
RAW_LOG(ERROR, argv_cstr[0]);
@@ -511,14 +514,6 @@ void RaiseProcessToHighPriority() {
// setpriority() or sched_getscheduler, but these all require extra rights.
}
-// Return value used by GetAppOutputInternal to encapsulate the various exit
-// scenarios from the function.
-enum GetAppOutputInternalResult {
- EXECUTE_FAILURE,
- EXECUTE_SUCCESS,
- GOT_MAX_OUTPUT,
-};
-
// Executes the application specified by |argv| and wait for it to exit. Stores
// the output (stdout) in |output|. If |do_search_path| is set, it searches the
// path for the application; in that case, |envp| must be null, and it will use
@@ -526,21 +521,14 @@ enum GetAppOutputInternalResult {
// specify the path of the application, and |envp| will be used as the
// 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.
-// The GOT_MAX_OUTPUT return value exists so a caller that asks for limited
-// output can treat this as a success, despite having an exit code of SIG_PIPE
-// due to us closing the output pipe.
-// In the case of EXECUTE_SUCCESS, the application exit code will be returned
-// in |*exit_code|, which should be checked to determine if the application
-// ran successfully.
-static GetAppOutputInternalResult GetAppOutputInternal(
+// The return value of the function indicates success or failure. In the case of
+// success, the application exit code will be returned in |*exit_code|, which
+// should be checked to determine if the application ran successfully.
+static bool GetAppOutputInternal(
const std::vector<std::string>& argv,
char* const envp[],
bool include_stderr,
std::string* output,
- size_t max_output,
bool do_search_path,
int* exit_code) {
// Doing a blocking wait for another command to finish counts as IO.
@@ -562,13 +550,13 @@ static GetAppOutputInternalResult GetAppOutputInternal(
DCHECK(!do_search_path ^ !envp);
if (pipe(pipe_fd) < 0)
- return EXECUTE_FAILURE;
+ return false;
switch (pid = fork()) {
case -1: // error
close(pipe_fd[0]);
close(pipe_fd[1]);
- return EXECUTE_FAILURE;
+ return false;
case 0: // child
{
// DANGER: no calls to malloc or locks are allowed from now on:
@@ -605,7 +593,7 @@ static GetAppOutputInternalResult GetAppOutputInternal(
for (size_t i = 0; i < argv.size(); i++)
argv_cstr[i] = const_cast<char*>(argv[i].c_str());
- argv_cstr[argv.size()] = NULL;
+ argv_cstr[argv.size()] = nullptr;
if (do_search_path)
execvp(argv_cstr[0], argv_cstr.get());
else
@@ -620,33 +608,21 @@ static GetAppOutputInternalResult GetAppOutputInternal(
close(pipe_fd[1]);
output->clear();
- char buffer[256];
- size_t output_buf_left = max_output;
- ssize_t bytes_read = 1; // A lie to properly handle |max_output == 0|
- // case in the logic below.
-
- while (output_buf_left > 0) {
- bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer,
- std::min(output_buf_left, sizeof(buffer))));
+
+ while (true) {
+ char buffer[256];
+ ssize_t bytes_read =
+ HANDLE_EINTR(read(pipe_fd[0], buffer, sizeof(buffer)));
if (bytes_read <= 0)
break;
output->append(buffer, bytes_read);
- output_buf_left -= static_cast<size_t>(bytes_read);
}
close(pipe_fd[0]);
// Always wait for exit code (even if we know we'll declare
// GOT_MAX_OUTPUT).
Process process(pid);
- bool success = process.WaitForExit(exit_code);
-
- // If we stopped because we read as much as we wanted, we return
- // GOT_MAX_OUTPUT (because the child may exit due to |SIGPIPE|).
- if (!output_buf_left && bytes_read > 0)
- return GOT_MAX_OUTPUT;
- else if (success)
- return EXECUTE_SUCCESS;
- return EXECUTE_FAILURE;
+ return process.WaitForExit(exit_code);
}
}
}
@@ -656,44 +632,27 @@ bool GetAppOutput(const CommandLine& cl, std::string* output) {
}
bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) {
- // Run |execve()| with the current environment and store "unlimited" data.
+ // Run |execve()| with the current environment.
int exit_code;
- GetAppOutputInternalResult result = GetAppOutputInternal(
- argv, NULL, false, output, std::numeric_limits<std::size_t>::max(), true,
- &exit_code);
- return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS;
+ bool result =
+ GetAppOutputInternal(argv, nullptr, false, output, true, &exit_code);
+ return result && 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,
- std::string* output, size_t max_output) {
- // Run |execve()| with the empty environment.
- char* const empty_environ = NULL;
+ // Run |execve()| with the current environment.
int exit_code;
- GetAppOutputInternalResult result = GetAppOutputInternal(
- cl.argv(), &empty_environ, false, output, max_output, false, &exit_code);
- return result == GOT_MAX_OUTPUT || (result == EXECUTE_SUCCESS &&
- exit_code == EXIT_SUCCESS);
+ bool result =
+ GetAppOutputInternal(cl.argv(), nullptr, true, output, true, &exit_code);
+ return result && exit_code == EXIT_SUCCESS;
}
bool GetAppOutputWithExitCode(const CommandLine& cl,
std::string* output,
int* exit_code) {
- // Run |execve()| with the current environment and store "unlimited" data.
- GetAppOutputInternalResult result = GetAppOutputInternal(
- cl.argv(), NULL, false, output, std::numeric_limits<std::size_t>::max(),
- true, exit_code);
- return result == EXECUTE_SUCCESS;
+ // Run |execve()| with the current environment.
+ return GetAppOutputInternal(cl.argv(), nullptr, false, output, true,
+ exit_code);
}
#endif // !defined(OS_NACL_NONSFI)
diff --git a/chromium/base/process/launch_win.cc b/chromium/base/process/launch_win.cc
index 97b59a5bfe4..1349b3e4af3 100644
--- a/chromium/base/process/launch_win.cc
+++ b/chromium/base/process/launch_win.cc
@@ -142,14 +142,7 @@ void RouteStdioToConsole(bool create_console_if_not_found) {
// _fileno(stdout) will return -2 (_NO_CONSOLE_FILENO) if stdout was
// invalid.
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.
-
- intptr_t stdout_handle = _get_osfhandle(_fileno(stdout));
- intptr_t stderr_handle = _get_osfhandle(_fileno(stderr));
- if (stdout_handle >= 0 || stderr_handle >= 0)
- return;
+ return;
}
if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
diff --git a/chromium/base/process/memory.cc b/chromium/base/process/memory.cc
index 75d45303eba..6349c08ca0a 100644
--- a/chromium/base/process/memory.cc
+++ b/chromium/base/process/memory.cc
@@ -9,6 +9,9 @@
namespace base {
+// Defined in memory_win.cc for Windows.
+#if !defined(OS_WIN)
+
namespace {
// Breakpad server classifies base::`anonymous namespace'::OnNoMemory as
@@ -25,6 +28,8 @@ void TerminateBecauseOutOfMemory(size_t size) {
OnNoMemory(size);
}
+#endif
+
// Defined in memory_mac.mm for Mac.
#if !defined(OS_MACOSX)
diff --git a/chromium/base/process/memory.h b/chromium/base/process/memory.h
index be669dd8476..77911cfc350 100644
--- a/chromium/base/process/memory.h
+++ b/chromium/base/process/memory.h
@@ -48,6 +48,20 @@ const int kMaxOomScore = 1000;
BASE_EXPORT bool AdjustOOMScore(ProcessId process, int score);
#endif
+#if defined(OS_WIN)
+namespace win {
+
+// Custom Windows exception code chosen to indicate an out of memory error.
+// See https://msdn.microsoft.com/en-us/library/het71c37.aspx.
+// "To make sure that you do not define a code that conflicts with an existing
+// exception code" ... "The resulting error code should therefore have the
+// highest four bits set to hexadecimal E."
+// 0xe0000008 was chosen arbitrarily, as 0x00000008 is ERROR_NOT_ENOUGH_MEMORY.
+const DWORD kOomExceptionCode = 0xe0000008;
+
+} // namespace win
+#endif
+
// Special allocator functions for callers that want to check for OOM.
// These will not abort if the allocation fails even if
// EnableTerminationOnOutOfMemory has been called.
diff --git a/chromium/base/process/memory_mac.mm b/chromium/base/process/memory_mac.mm
index 32fdd38821d..bac75aeab15 100644
--- a/chromium/base/process/memory_mac.mm
+++ b/chromium/base/process/memory_mac.mm
@@ -248,7 +248,7 @@ void oom_killer_new() {
// === Core Foundation CFAllocators ===
bool CanGetContextForCFAllocator() {
- return !base::mac::IsOSLaterThanSierra_DontCallThis();
+ return !base::mac::IsOSLaterThan10_12_DontCallThis();
}
CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) {
diff --git a/chromium/base/process/memory_stubs.cc b/chromium/base/process/memory_stubs.cc
index 7ed012d8803..787d9aef217 100644
--- a/chromium/base/process/memory_stubs.cc
+++ b/chromium/base/process/memory_stubs.cc
@@ -19,6 +19,10 @@ bool AdjustOOMScore(ProcessId process, int score) {
return false;
}
+void TerminateBecauseOutOfMemory(size_t size) {
+ abort();
+}
+
// UncheckedMalloc and Calloc exist so that platforms making use of
// EnableTerminationOnOutOfMemory have a way to allocate memory without
// crashing. This _stubs.cc file is for platforms that do not support
diff --git a/chromium/base/process/memory_unittest.cc b/chromium/base/process/memory_unittest.cc
index ec2ed9f1869..0be2d440063 100644
--- a/chromium/base/process/memory_unittest.cc
+++ b/chromium/base/process/memory_unittest.cc
@@ -11,6 +11,7 @@
#include <limits>
#include "base/allocator/allocator_check.h"
+#include "base/allocator/features.h"
#include "base/compiler_specific.h"
#include "base/debug/alias.h"
#include "base/memory/aligned_memory.h"
@@ -26,7 +27,6 @@
#endif
#if defined(OS_MACOSX)
#include <malloc/malloc.h>
-#include "base/mac/mac_util.h"
#include "base/process/memory_unittest_mac.h"
#endif
#if defined(OS_LINUX)
@@ -82,17 +82,23 @@ TEST(MemoryTest, AllocatorShimWorking) {
ASSERT_TRUE(base::allocator::IsAllocatorInitialized());
}
-// Android doesn't implement set_new_handler, so we can't use the
-// OutOfMemoryTest cases. OpenBSD does not support these tests either.
-// Don't test these on ASan/TSan/MSan configurations: only test the real
-// allocator.
+// OpenBSD does not support these tests. Don't test these on ASan/TSan/MSan
+// configurations: only test the real allocator.
// Windows only supports these tests with the allocator shim in place.
-#if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && \
- !(defined(OS_WIN) && !defined(ALLOCATOR_SHIM)) && \
+#if !defined(OS_OPENBSD) && \
+ BUILDFLAG(ENABLE_WIN_ALLOCATOR_SHIM_TESTS) && \
!defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
namespace {
-const char *kOomRegex = "Out of memory";
+#if defined(OS_WIN)
+// Windows raises an exception rather than using LOG(FATAL) in order to make the
+// exit code unique to OOM.
+const char* kOomRegex = "";
+const int kExitCode = base::win::kOomExceptionCode;
+#else
+const char* kOomRegex = "Out of memory";
+const int kExitCode = 1;
+#endif
} // namespace
class OutOfMemoryTest : public testing::Test {
@@ -128,112 +134,112 @@ class OutOfMemoryDeathTest : public OutOfMemoryTest {
};
TEST_F(OutOfMemoryDeathTest, New) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = operator new(test_size_);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, NewArray) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = new char[test_size_];
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, Malloc) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = malloc(test_size_);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, Realloc) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = realloc(NULL, test_size_);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, Calloc) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = calloc(1024, test_size_ / 1024L);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, AlignedAlloc) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = base::AlignedAlloc(test_size_, 8);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
// POSIX does not define an aligned realloc function.
#if defined(OS_WIN)
TEST_F(OutOfMemoryDeathTest, AlignedRealloc) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = _aligned_realloc(NULL, test_size_, 8);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
#endif // defined(OS_WIN)
-// OS X has no 2Gb allocation limit.
+// OS X and Android have no 2Gb allocation limit.
// See https://crbug.com/169327.
-#if !defined(OS_MACOSX)
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
TEST_F(OutOfMemoryDeathTest, SecurityNew) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = operator new(insecure_test_size_);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, SecurityNewArray) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = new char[insecure_test_size_];
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, SecurityMalloc) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = malloc(insecure_test_size_);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, SecurityRealloc) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = realloc(NULL, insecure_test_size_);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, SecurityCalloc) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = calloc(1024, insecure_test_size_ / 1024L);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, SecurityAlignedAlloc) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = base::AlignedAlloc(insecure_test_size_, 8);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
// POSIX does not define an aligned realloc function.
#if defined(OS_WIN)
TEST_F(OutOfMemoryDeathTest, SecurityAlignedRealloc) {
- ASSERT_DEATH({
+ ASSERT_EXIT({
SetUpInDeathAssert();
value_ = _aligned_realloc(NULL, insecure_test_size_, 8);
- }, kOomRegex);
+ }, testing::ExitedWithCode(kExitCode), kOomRegex);
}
#endif // defined(OS_WIN)
-#endif // !defined(OS_MACOSX)
+#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
#if defined(OS_LINUX)
@@ -405,17 +411,7 @@ class OutOfMemoryHandledTest : public OutOfMemoryTest {
// TODO(b.kelemen): make UncheckedMalloc and UncheckedCalloc work
// on Windows as well.
-// UncheckedMalloc() and UncheckedCalloc() work as regular malloc()/calloc()
-// under sanitizer tools.
-#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
TEST_F(OutOfMemoryHandledTest, UncheckedMalloc) {
-#if defined(OS_MACOSX) && ARCH_CPU_32_BITS
- // The Mavericks malloc library changed in a way which breaks the tricks used
- // to implement EnableTerminationOnOutOfMemory() with UncheckedMalloc() under
- // 32-bit. The 64-bit malloc library works as desired without tricks.
- if (base::mac::IsOSMavericksOrLater())
- return;
-#endif
EXPECT_TRUE(base::UncheckedMalloc(kSafeMallocSize, &value_));
EXPECT_TRUE(value_ != NULL);
free(value_);
@@ -425,13 +421,6 @@ TEST_F(OutOfMemoryHandledTest, UncheckedMalloc) {
}
TEST_F(OutOfMemoryHandledTest, UncheckedCalloc) {
-#if defined(OS_MACOSX) && ARCH_CPU_32_BITS
- // The Mavericks malloc library changed in a way which breaks the tricks used
- // to implement EnableTerminationOnOutOfMemory() with UncheckedCalloc() under
- // 32-bit. The 64-bit malloc library works as desired without tricks.
- if (base::mac::IsOSMavericksOrLater())
- return;
-#endif
EXPECT_TRUE(base::UncheckedCalloc(1, kSafeMallocSize, &value_));
EXPECT_TRUE(value_ != NULL);
const char* bytes = static_cast<const char*>(value_);
@@ -450,6 +439,5 @@ TEST_F(OutOfMemoryHandledTest, UncheckedCalloc) {
EXPECT_FALSE(base::UncheckedCalloc(1, test_size_, &value_));
EXPECT_TRUE(value_ == NULL);
}
-#endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-#endif // !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !(defined(OS_WIN) &&
- // !defined(ALLOCATOR_SHIM)) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+#endif // !defined(OS_OPENBSD) && BUILDFLAG(ENABLE_WIN_ALLOCATOR_SHIM_TESTS) &&
+ // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
diff --git a/chromium/base/process/memory_win.cc b/chromium/base/process/memory_win.cc
index 17d588aab73..d433020debb 100644
--- a/chromium/base/process/memory_win.cc
+++ b/chromium/base/process/memory_win.cc
@@ -7,8 +7,7 @@
#include <new.h>
#include <psapi.h>
#include <stddef.h>
-
-#include "base/logging.h"
+#include <windows.h>
// malloc_unchecked is required to implement UncheckedMalloc properly.
// It's provided by allocator_shim_win.cc but since that's not always present,
@@ -30,25 +29,27 @@ namespace base {
namespace {
#pragma warning(push)
-#pragma warning(disable: 4702)
+#pragma warning(disable: 4702) // Unreachable code after the _exit.
-int OnNoMemory(size_t size) {
+NOINLINE 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.
- LOG(FATAL) << "Out of memory, size = " << size;
-
+ // https://msdn.microsoft.com/en-us/library/het71c37.aspx
+ ::RaiseException(win::kOomExceptionCode, EXCEPTION_NONCONTINUABLE, 0,
+ nullptr);
// Safety check, make sure process exits here.
- _exit(1);
+ _exit(win::kOomExceptionCode);
return 0;
}
#pragma warning(pop)
-// HeapSetInformation function pointer.
-typedef BOOL (WINAPI* HeapSetFn)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T);
-
} // namespace
+void TerminateBecauseOutOfMemory(size_t size) {
+ OnNoMemory(size);
+}
+
void EnableTerminationOnHeapCorruption() {
// Ignore the result code. Supported on XP SP3 and Vista.
HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
diff --git a/chromium/base/process/process_metrics.cc b/chromium/base/process/process_metrics.cc
index 0b387264315..cc6532c8dca 100644
--- a/chromium/base/process/process_metrics.cc
+++ b/chromium/base/process/process_metrics.cc
@@ -46,7 +46,7 @@ std::unique_ptr<Value> SystemMetrics::ToValue() const {
return std::move(res);
}
-ProcessMetrics* ProcessMetrics::CreateCurrentProcessMetrics() {
+std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateCurrentProcessMetrics() {
#if !defined(OS_MACOSX) || defined(OS_IOS)
return CreateProcessMetrics(base::GetCurrentProcessHandle());
#else
diff --git a/chromium/base/process/process_metrics.h b/chromium/base/process/process_metrics.h
index 57cb3abec0d..d9c9952201b 100644
--- a/chromium/base/process/process_metrics.h
+++ b/chromium/base/process/process_metrics.h
@@ -11,6 +11,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/base_export.h"
@@ -103,22 +104,22 @@ class BASE_EXPORT ProcessMetrics {
~ProcessMetrics();
// Creates a ProcessMetrics for the specified process.
- // The caller owns the returned object.
#if !defined(OS_MACOSX) || defined(OS_IOS)
- static ProcessMetrics* CreateProcessMetrics(ProcessHandle process);
+ static std::unique_ptr<ProcessMetrics> CreateProcessMetrics(
+ ProcessHandle process);
#else
// The port provider needs to outlive the ProcessMetrics object returned by
// this function. If NULL is passed as provider, the returned object
// only returns valid metrics if |process| is the current process.
- static ProcessMetrics* CreateProcessMetrics(ProcessHandle process,
- PortProvider* port_provider);
+ static std::unique_ptr<ProcessMetrics> CreateProcessMetrics(
+ ProcessHandle process,
+ PortProvider* port_provider);
#endif // !defined(OS_MACOSX) || defined(OS_IOS)
// Creates a ProcessMetrics for the current process. This a cross-platform
// convenience wrapper for CreateProcessMetrics().
- // The caller owns the returned object.
- static ProcessMetrics* CreateCurrentProcessMetrics();
+ static std::unique_ptr<ProcessMetrics> CreateCurrentProcessMetrics();
// Returns the current space allocated for the pagefile, in bytes (these pages
// may or may not be in memory). On Linux, this returns the total virtual
@@ -295,9 +296,9 @@ struct BASE_EXPORT SystemMemoryInfoKB {
int dirty;
// vmstats data.
- int pswpin;
- int pswpout;
- int pgmajfault;
+ unsigned long pswpin;
+ unsigned long pswpout;
+ unsigned long pgmajfault;
#endif // defined(OS_ANDROID) || defined(OS_LINUX)
#if defined(OS_CHROMEOS)
@@ -374,6 +375,9 @@ BASE_EXPORT bool IsValidDiskName(const std::string& candidate);
// Retrieves data from /proc/diskstats about system-wide disk I/O.
// Fills in the provided |diskinfo| structure. Returns true on success.
BASE_EXPORT bool GetSystemDiskInfo(SystemDiskInfo* diskinfo);
+
+// Returns the amount of time spent in user space since boot across all CPUs.
+BASE_EXPORT TimeDelta GetUserCpuTimeSinceBoot();
#endif // defined(OS_LINUX) || defined(OS_ANDROID)
#if defined(OS_CHROMEOS)
diff --git a/chromium/base/process/process_metrics_freebsd.cc b/chromium/base/process/process_metrics_freebsd.cc
index 5fd93cbe1c9..686f6338724 100644
--- a/chromium/base/process/process_metrics_freebsd.cc
+++ b/chromium/base/process/process_metrics_freebsd.cc
@@ -10,20 +10,21 @@
#include <unistd.h>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/sys_info.h"
namespace base {
ProcessMetrics::ProcessMetrics(ProcessHandle process)
: process_(process),
+ processor_count_(SysInfo::NumberOfProcessors()),
last_system_time_(0),
- last_cpu_(0) {
- processor_count_ = base::SysInfo::NumberOfProcessors();
-}
+ last_cpu_(0) {}
// static
-ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
- return new ProcessMetrics(process);
+std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
+ ProcessHandle process) {
+ return WrapUnique(new ProcessMetrics(process));
}
size_t ProcessMetrics::GetPagefileUsage() const {
diff --git a/chromium/base/process/process_metrics_ios.cc b/chromium/base/process/process_metrics_ios.cc
index 8f9806e132a..e6b01192b59 100644
--- a/chromium/base/process/process_metrics_ios.cc
+++ b/chromium/base/process/process_metrics_ios.cc
@@ -9,6 +9,7 @@
#include <stddef.h>
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
namespace base {
@@ -25,10 +26,7 @@ bool GetTaskInfo(task_basic_info_64* task_info_data) {
} // namespace
-SystemMemoryInfoKB::SystemMemoryInfoKB() {
- total = 0;
- free = 0;
-}
+SystemMemoryInfoKB::SystemMemoryInfoKB() : total(0), free(0) {}
SystemMemoryInfoKB::SystemMemoryInfoKB(const SystemMemoryInfoKB& other) =
default;
@@ -38,8 +36,9 @@ ProcessMetrics::ProcessMetrics(ProcessHandle process) {}
ProcessMetrics::~ProcessMetrics() {}
// static
-ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
- return new ProcessMetrics(process);
+std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
+ ProcessHandle process) {
+ return WrapUnique(new ProcessMetrics(process));
}
double ProcessMetrics::GetCPUUsage() {
diff --git a/chromium/base/process/process_metrics_linux.cc b/chromium/base/process/process_metrics_linux.cc
index 3d27656d6ac..b14aa210bd5 100644
--- a/chromium/base/process/process_metrics_linux.cc
+++ b/chromium/base/process/process_metrics_linux.cc
@@ -17,6 +17,7 @@
#include "base/files/dir_reader_posix.h"
#include "base/files/file_util.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/process/internal_linux.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -72,8 +73,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<StringPiece> split_value_str = SplitStringPiece(
- value_str, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ std::vector<StringPiece> split_value_str =
+ SplitStringPiece(value_str, " ", TRIM_WHITESPACE, SPLIT_WANT_ALL);
if (split_value_str.size() != 2 || split_value_str[1] != "kB") {
NOTREACHED();
return 0;
@@ -163,8 +164,9 @@ int GetProcessCPU(pid_t pid) {
} // namespace
// static
-ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
- return new ProcessMetrics(process);
+std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
+ ProcessHandle process) {
+ return WrapUnique(new ProcessMetrics(process));
}
// On linux, we return vsize.
@@ -354,8 +356,7 @@ bool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage)
}
std::vector<std::string> totmaps_fields = SplitString(
- totmaps_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY);
+ totmaps_data, kWhitespaceASCII, KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
DCHECK_EQ("Pss:", totmaps_fields[kPssIndex-1]);
DCHECK_EQ("Private_Clean:", totmaps_fields[kPrivate_CleanIndex - 1]);
@@ -406,8 +407,8 @@ bool ProcessMetrics::GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage)
return false;
}
- std::vector<StringPiece> statm_vec = SplitStringPiece(
- statm, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ std::vector<StringPiece> statm_vec =
+ SplitStringPiece(statm, " ", TRIM_WHITESPACE, SPLIT_WANT_ALL);
if (statm_vec.size() != 7)
return false; // Not the format we expect.
@@ -686,12 +687,16 @@ bool ParseProcVmstat(const std::string& vmstat_data,
if (tokens.size() != 2)
continue;
+ uint64_t val;
+ if (!StringToUint64(tokens[1], &val))
+ continue;
+
if (tokens[0] == "pswpin") {
- StringToInt(tokens[1], &meminfo->pswpin);
+ meminfo->pswpin = val;
} else if (tokens[0] == "pswpout") {
- StringToInt(tokens[1], &meminfo->pswpout);
+ meminfo->pswpout = val;
} else if (tokens[0] == "pgmajfault") {
- StringToInt(tokens[1], &meminfo->pgmajfault);
+ meminfo->pgmajfault = val;
}
}
@@ -907,6 +912,10 @@ bool GetSystemDiskInfo(SystemDiskInfo* diskinfo) {
return true;
}
+TimeDelta GetUserCpuTimeSinceBoot() {
+ return internal::GetUserCpuTimeSinceBoot();
+}
+
#if defined(OS_CHROMEOS)
std::unique_ptr<Value> SwapInfo::ToValue() const {
std::unique_ptr<DictionaryValue> res(new DictionaryValue());
diff --git a/chromium/base/process/process_metrics_mac.cc b/chromium/base/process/process_metrics_mac.cc
index b3e87178ab4..7fc931748ae 100644
--- a/chromium/base/process/process_metrics_mac.cc
+++ b/chromium/base/process/process_metrics_mac.cc
@@ -15,6 +15,7 @@
#include "base/logging.h"
#include "base/mac/mach_logging.h"
#include "base/mac/scoped_mach_port.h"
+#include "base/memory/ptr_util.h"
#include "base/sys_info.h"
#if !defined(TASK_POWER_INFO)
@@ -79,10 +80,7 @@ bool IsAddressInSharedRegion(mach_vm_address_t addr, cpu_type_t type) {
} // namespace
-SystemMemoryInfoKB::SystemMemoryInfoKB() {
- total = 0;
- free = 0;
-}
+SystemMemoryInfoKB::SystemMemoryInfoKB() : total(0), free(0) {}
SystemMemoryInfoKB::SystemMemoryInfoKB(const SystemMemoryInfoKB& other) =
default;
@@ -94,10 +92,10 @@ SystemMemoryInfoKB::SystemMemoryInfoKB(const SystemMemoryInfoKB& other) =
// otherwise return 0.
// static
-ProcessMetrics* ProcessMetrics::CreateProcessMetrics(
+std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
ProcessHandle process,
PortProvider* port_provider) {
- return new ProcessMetrics(process, port_provider);
+ return WrapUnique(new ProcessMetrics(process, port_provider));
}
size_t ProcessMetrics::GetPagefileUsage() const {
@@ -145,7 +143,7 @@ bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes,
// The same region can be referenced multiple times. To avoid double counting
// we need to keep track of which regions we've already counted.
- base::hash_set<int> seen_objects;
+ hash_set<int> seen_objects;
// We iterate through each VM region in the task's address map. For shared
// memory we add up all the pages that are marked as shared. Like libtop we
diff --git a/chromium/base/process/process_metrics_openbsd.cc b/chromium/base/process/process_metrics_openbsd.cc
index 3f76cc222d9..58033aef62e 100644
--- a/chromium/base/process/process_metrics_openbsd.cc
+++ b/chromium/base/process/process_metrics_openbsd.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/macros.h"
#include "base/process/process_metrics.h"
#include <stddef.h>
@@ -10,11 +9,16 @@
#include <sys/param.h>
#include <sys/sysctl.h>
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/sys_info.h"
+
namespace base {
// static
-ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
- return new ProcessMetrics(process);
+std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
+ ProcessHandle process) {
+ return WrapUnique(new ProcessMetrics(process));
}
size_t ProcessMetrics::GetPagefileUsage() const {
@@ -136,11 +140,9 @@ double ProcessMetrics::GetCPUUsage() {
ProcessMetrics::ProcessMetrics(ProcessHandle process)
: process_(process),
+ processor_count_(SysInfo::NumberOfProcessors()),
last_system_time_(0),
- last_cpu_(0) {
-
- processor_count_ = base::SysInfo::NumberOfProcessors();
-}
+ last_cpu_(0) {}
size_t GetSystemCommitCharge() {
int mib[] = { CTL_VM, VM_METER };
diff --git a/chromium/base/process/process_metrics_posix.cc b/chromium/base/process/process_metrics_posix.cc
index fad581eece7..13acf2ea34f 100644
--- a/chromium/base/process/process_metrics_posix.cc
+++ b/chromium/base/process/process_metrics_posix.cc
@@ -33,6 +33,8 @@ static const rlim_t kSystemDefaultMaxFds = 256;
static const rlim_t kSystemDefaultMaxFds = 8192;
#elif defined(OS_FREEBSD)
static const rlim_t kSystemDefaultMaxFds = 8192;
+#elif defined(OS_NETBSD)
+static const rlim_t kSystemDefaultMaxFds = 1024;
#elif defined(OS_OPENBSD)
static const rlim_t kSystemDefaultMaxFds = 256;
#elif defined(OS_ANDROID)
diff --git a/chromium/base/process/process_metrics_unittest.cc b/chromium/base/process/process_metrics_unittest.cc
index 4c5b71d0bd5..3e059b48a45 100644
--- a/chromium/base/process/process_metrics_unittest.cc
+++ b/chromium/base/process/process_metrics_unittest.cc
@@ -286,13 +286,13 @@ TEST_F(SystemMetricsTest, ParseVmstat) {
"pgrefill_high 0\n"
"pgrefill_movable 0\n";
EXPECT_TRUE(ParseProcVmstat(valid_input1, &meminfo));
- EXPECT_EQ(meminfo.pswpin, 179);
- EXPECT_EQ(meminfo.pswpout, 406);
- EXPECT_EQ(meminfo.pgmajfault, 487192);
+ EXPECT_EQ(179LU, meminfo.pswpin);
+ EXPECT_EQ(406LU, meminfo.pswpout);
+ EXPECT_EQ(487192LU, meminfo.pgmajfault);
EXPECT_TRUE(ParseProcVmstat(valid_input2, &meminfo));
- EXPECT_EQ(meminfo.pswpin, 12);
- EXPECT_EQ(meminfo.pswpout, 901);
- EXPECT_EQ(meminfo.pgmajfault, 2023);
+ EXPECT_EQ(12LU, meminfo.pswpin);
+ EXPECT_EQ(901LU, meminfo.pswpout);
+ EXPECT_EQ(2023LU, meminfo.pgmajfault);
}
#endif // defined(OS_LINUX) || defined(OS_ANDROID)
@@ -488,7 +488,7 @@ MULTIPROCESS_TEST_MAIN(ChildMain) {
TEST(ProcessMetricsTest, GetOpenFdCount) {
ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- const FilePath temp_path = temp_dir.path();
+ const FilePath temp_path = temp_dir.GetPath();
CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
child_command_line.AppendSwitchPath(kTempDirFlag, temp_path);
Process child = SpawnMultiProcessTestChild(
diff --git a/chromium/base/process/process_metrics_win.cc b/chromium/base/process/process_metrics_win.cc
index 46e4b8d8494..5b2777bb364 100644
--- a/chromium/base/process/process_metrics_win.cc
+++ b/chromium/base/process/process_metrics_win.cc
@@ -13,6 +13,8 @@
#include <algorithm>
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/process/memory.h"
#include "base/sys_info.h"
namespace base {
@@ -29,12 +31,8 @@ typedef NTSTATUS(WINAPI* NTQUERYSYSTEMINFORMATION)(
} // namespace
-SystemMemoryInfoKB::SystemMemoryInfoKB() {
- total = 0;
- free = 0;
- swap_total = 0;
- swap_free = 0;
-}
+SystemMemoryInfoKB::SystemMemoryInfoKB()
+ : total(0), free(0), swap_total(0), swap_free(0) {}
SystemMemoryInfoKB::SystemMemoryInfoKB(const SystemMemoryInfoKB& other) =
default;
@@ -42,8 +40,9 @@ SystemMemoryInfoKB::SystemMemoryInfoKB(const SystemMemoryInfoKB& other) =
ProcessMetrics::~ProcessMetrics() { }
// static
-ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
- return new ProcessMetrics(process);
+std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
+ ProcessHandle process) {
+ return WrapUnique(new ProcessMetrics(process));
}
size_t ProcessMetrics::GetPagefileUsage() const {
@@ -142,6 +141,36 @@ void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const {
usage->priv = committed_private / 1024;
}
+namespace {
+
+class WorkingSetInformationBuffer {
+ public:
+ WorkingSetInformationBuffer() {}
+ ~WorkingSetInformationBuffer() { Clear(); }
+
+ bool Reserve(size_t size) {
+ Clear();
+ // Use UncheckedMalloc here because this can be called from the code
+ // that handles low memory condition.
+ return UncheckedMalloc(size, reinterpret_cast<void**>(&buffer_));
+ }
+
+ PSAPI_WORKING_SET_INFORMATION* get() { return buffer_; }
+ const PSAPI_WORKING_SET_INFORMATION* operator ->() const { return buffer_; }
+
+ private:
+ void Clear() {
+ free(buffer_);
+ buffer_ = nullptr;
+ }
+
+ PSAPI_WORKING_SET_INFORMATION* buffer_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(WorkingSetInformationBuffer);
+};
+
+} // namespace
+
bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
size_t ws_private = 0;
size_t ws_shareable = 0;
@@ -151,40 +180,33 @@ bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
memset(ws_usage, 0, sizeof(*ws_usage));
DWORD number_of_entries = 4096; // Just a guess.
- PSAPI_WORKING_SET_INFORMATION* buffer = NULL;
+ WorkingSetInformationBuffer buffer;
int retries = 5;
for (;;) {
DWORD buffer_size = sizeof(PSAPI_WORKING_SET_INFORMATION) +
(number_of_entries * sizeof(PSAPI_WORKING_SET_BLOCK));
- // if we can't expand the buffer, don't leak the previous
- // contents or pass a NULL pointer to QueryWorkingSet
- PSAPI_WORKING_SET_INFORMATION* new_buffer =
- reinterpret_cast<PSAPI_WORKING_SET_INFORMATION*>(
- realloc(buffer, buffer_size));
- if (!new_buffer) {
- free(buffer);
+ if (!buffer.Reserve(buffer_size))
return false;
- }
- buffer = new_buffer;
// Call the function once to get number of items
- if (QueryWorkingSet(process_, buffer, buffer_size))
+ if (QueryWorkingSet(process_, buffer.get(), buffer_size))
break; // Success
- if (GetLastError() != ERROR_BAD_LENGTH) {
- free(buffer);
+ if (GetLastError() != ERROR_BAD_LENGTH)
return false;
- }
number_of_entries = static_cast<DWORD>(buffer->NumberOfEntries);
// Maybe some entries are being added right now. Increase the buffer to
- // take that into account.
- number_of_entries = static_cast<DWORD>(number_of_entries * 1.25);
+ // take that into account. Increasing by 10% should generally be enough,
+ // especially considering the potentially low memory condition during the
+ // call (when called from OomMemoryDetails) and the potentially high
+ // number of entries (300K was observed in crash dumps).
+ number_of_entries = static_cast<DWORD>(number_of_entries * 1.1);
if (--retries == 0) {
- free(buffer); // If we're looping, eventually fail.
+ // If we're looping, eventually fail.
return false;
}
}
@@ -207,7 +229,6 @@ bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
ws_usage->priv = ws_private * PAGESIZE_KB;
ws_usage->shareable = ws_shareable * PAGESIZE_KB;
ws_usage->shared = ws_shared * PAGESIZE_KB;
- free(buffer);
return true;
}
@@ -263,35 +284,8 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
ProcessMetrics::ProcessMetrics(ProcessHandle process)
: process_(process),
- processor_count_(base::SysInfo::NumberOfProcessors()),
- last_system_time_(0) {
-}
-
-// GetPerformanceInfo is not available on WIN2K. So we'll
-// load it on-the-fly.
-const wchar_t kPsapiDllName[] = L"psapi.dll";
-typedef BOOL (WINAPI *GetPerformanceInfoFunction) (
- PPERFORMANCE_INFORMATION pPerformanceInformation,
- DWORD cb);
-
-// Beware of races if called concurrently from multiple threads.
-static BOOL InternalGetPerformanceInfo(
- PPERFORMANCE_INFORMATION pPerformanceInformation, DWORD cb) {
- static GetPerformanceInfoFunction GetPerformanceInfo_func = NULL;
- if (!GetPerformanceInfo_func) {
- HMODULE psapi_dll = ::GetModuleHandle(kPsapiDllName);
- if (psapi_dll)
- GetPerformanceInfo_func = reinterpret_cast<GetPerformanceInfoFunction>(
- GetProcAddress(psapi_dll, "GetPerformanceInfo"));
-
- if (!GetPerformanceInfo_func) {
- // The function could not be loaded!
- memset(pPerformanceInformation, 0, cb);
- return FALSE;
- }
- }
- return GetPerformanceInfo_func(pPerformanceInformation, cb);
-}
+ processor_count_(SysInfo::NumberOfProcessors()),
+ last_system_time_(0) {}
size_t GetSystemCommitCharge() {
// Get the System Page Size.
@@ -299,7 +293,7 @@ size_t GetSystemCommitCharge() {
GetSystemInfo(&system_info);
PERFORMANCE_INFORMATION info;
- if (!InternalGetPerformanceInfo(&info, sizeof(info))) {
+ if (!GetPerformanceInfo(&info, sizeof(info))) {
DLOG(ERROR) << "Failed to fetch internal performance info.";
return 0;
}
diff --git a/chromium/base/process/process_posix.cc b/chromium/base/process/process_posix.cc
index ade82e5ce66..a9d745eeead 100644
--- a/chromium/base/process/process_posix.cc
+++ b/chromium/base/process/process_posix.cc
@@ -9,6 +9,7 @@
#include <sys/resource.h>
#include <sys/wait.h>
+#include "base/debug/activity_tracker.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
@@ -354,6 +355,9 @@ bool Process::WaitForExit(int* exit_code) {
}
bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) {
+ // Record the event that this thread is blocking upon (for hang diagnosis).
+ base::debug::ScopedProcessWaitActivity process_activity(this);
+
return WaitForExitWithTimeoutImpl(Handle(), exit_code, timeout);
}
diff --git a/chromium/base/process/process_util_unittest.cc b/chromium/base/process/process_util_unittest.cc
index c162fb20366..87fdd012309 100644
--- a/chromium/base/process/process_util_unittest.cc
+++ b/chromium/base/process/process_util_unittest.cc
@@ -60,7 +60,6 @@
#if defined(OS_MACOSX)
#include <mach/vm_param.h>
#include <malloc/malloc.h>
-#include "base/mac/mac_util.h"
#endif
#if defined(OS_ANDROID)
#include "third_party/lss/linux_syscall_support.h"
@@ -572,10 +571,6 @@ int change_fdguard_np(int fd,
// <http://crbug.com/338157>. This function allows querying whether the file
// descriptor is guarded before attempting to close it.
bool CanGuardFd(int fd) {
- // The syscall is first provided in 10.9/Mavericks.
- if (!base::mac::IsOSMavericksOrLater())
- return true;
-
// Saves the original flags to reset later.
int original_fdflags = 0;
@@ -844,118 +839,6 @@ TEST_F(ProcessUtilTest, GetAppOutput) {
#endif // defined(OS_ANDROID)
}
-// Flakes on Android, crbug.com/375840
-#if defined(OS_ANDROID)
-#define MAYBE_GetAppOutputRestricted DISABLED_GetAppOutputRestricted
-#else
-#define MAYBE_GetAppOutputRestricted GetAppOutputRestricted
-#endif
-TEST_F(ProcessUtilTest, MAYBE_GetAppOutputRestricted) {
- // Unfortunately, since we can't rely on the path, we need to know where
- // everything is. So let's use /bin/sh, which is on every POSIX system, and
- // its built-ins.
- std::vector<std::string> argv;
- argv.push_back(std::string(kShellPath)); // argv[0]
- argv.push_back("-c"); // argv[1]
-
- // On success, should set |output|. We use |/bin/sh -c 'exit 0'| instead of
- // |true| since the location of the latter may be |/bin| or |/usr/bin| (and we
- // need absolute paths).
- argv.push_back("exit 0"); // argv[2]; equivalent to "true"
- std::string output = "abc";
- EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
- 100));
- EXPECT_STREQ("", output.c_str());
-
- argv[2] = "exit 1"; // equivalent to "false"
- output = "before";
- EXPECT_FALSE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
- 100));
- EXPECT_STREQ("", output.c_str());
-
- // Amount of output exactly equal to space allowed.
- argv[2] = "echo 123456789"; // (the sh built-in doesn't take "-n")
- output.clear();
- EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
- 10));
- EXPECT_STREQ("123456789\n", output.c_str());
-
- // Amount of output greater than space allowed.
- output.clear();
- EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
- 5));
- EXPECT_STREQ("12345", output.c_str());
-
- // Amount of output less than space allowed.
- output.clear();
- EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
- 15));
- EXPECT_STREQ("123456789\n", output.c_str());
-
- // Zero space allowed.
- output = "abc";
- EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
- 0));
- EXPECT_STREQ("", output.c_str());
-}
-
-#if !defined(OS_MACOSX) && !defined(OS_OPENBSD)
-// TODO(benwells): GetAppOutputRestricted should terminate applications
-// with SIGPIPE when we have enough output. http://crbug.com/88502
-TEST_F(ProcessUtilTest, GetAppOutputRestrictedSIGPIPE) {
- std::vector<std::string> argv;
- std::string output;
-
- argv.push_back(std::string(kShellPath)); // argv[0]
- argv.push_back("-c");
-#if defined(OS_ANDROID)
- argv.push_back("while echo 12345678901234567890; do :; done");
- EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
- 10));
- EXPECT_STREQ("1234567890", output.c_str());
-#else // defined(OS_ANDROID)
- argv.push_back("yes");
- EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
- 10));
- EXPECT_STREQ("y\ny\ny\ny\ny\n", output.c_str());
-#endif // !defined(OS_ANDROID)
-}
-#endif // !defined(OS_MACOSX) && !defined(OS_OPENBSD)
-
-#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]
- argv.push_back("-c"); // argv[1]
- argv.push_back("echo 123456789012345678901234567890"); // argv[2]
-
- // Run |GetAppOutputRestricted()| 300 (> default per-user processes on Mac OS
- // 10.5) times with an output buffer big enough to capture all output.
- for (int i = 0; i < 300; i++) {
- std::string output;
- EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
- 100));
- EXPECT_STREQ("123456789012345678901234567890\n", output.c_str());
- }
-
- // Ditto, but with an output buffer too small to capture all output.
- for (int i = 0; i < 300; i++) {
- std::string output;
- EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
- 10));
- EXPECT_STREQ("1234567890", output.c_str());
- }
-}
-
TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) {
// Test getting output from a successful application.
std::vector<std::string> argv;
diff --git a/chromium/base/process/process_win.cc b/chromium/base/process/process_win.cc
index 8e508a1b1fb..6629f4565a7 100644
--- a/chromium/base/process/process_win.cc
+++ b/chromium/base/process/process_win.cc
@@ -4,6 +4,7 @@
#include "base/process/process.h"
+#include "base/debug/activity_tracker.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/kill.h"
@@ -142,6 +143,9 @@ bool Process::WaitForExit(int* exit_code) {
}
bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) {
+ // Record the event that this thread is blocking upon (for hang diagnosis).
+ base::debug::ScopedProcessWaitActivity process_activity(this);
+
// Limit timeout to INFINITE.
DWORD timeout_ms = saturated_cast<DWORD>(timeout.InMilliseconds());
if (::WaitForSingleObject(Handle(), timeout_ms) != WAIT_OBJECT_0)