summaryrefslogtreecommitdiffstats
path: root/chromium/base/process
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/base/process
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/base/process')
-rw-r--r--chromium/base/process/internal_linux.cc13
-rw-r--r--chromium/base/process/internal_linux.h15
-rw-r--r--chromium/base/process/kill_mac.cc11
-rw-r--r--chromium/base/process/kill_posix.cc63
-rw-r--r--chromium/base/process/kill_win.cc10
-rw-r--r--chromium/base/process/launch.cc13
-rw-r--r--chromium/base/process/launch.h48
-rw-r--r--chromium/base/process/launch_mac.cc20
-rw-r--r--chromium/base/process/launch_posix.cc104
-rw-r--r--chromium/base/process/launch_win.cc43
-rw-r--r--chromium/base/process/memory.cc30
-rw-r--r--chromium/base/process/memory.h34
-rw-r--r--chromium/base/process/memory_linux.cc40
-rw-r--r--chromium/base/process/memory_mac.mm53
-rw-r--r--chromium/base/process/memory_unittest.cc96
-rw-r--r--chromium/base/process/memory_win.cc11
-rw-r--r--chromium/base/process/process_handle.h4
-rw-r--r--chromium/base/process/process_handle_freebsd.cc1
-rw-r--r--chromium/base/process/process_handle_linux.cc2
-rw-r--r--chromium/base/process/process_handle_mac.cc9
-rw-r--r--chromium/base/process/process_info_linux.cc4
-rw-r--r--chromium/base/process/process_info_mac.cc2
-rw-r--r--chromium/base/process/process_iterator.h4
-rw-r--r--chromium/base/process/process_iterator_freebsd.cc2
-rw-r--r--chromium/base/process/process_iterator_linux.cc4
-rw-r--r--chromium/base/process/process_iterator_mac.cc1
-rw-r--r--chromium/base/process/process_linux.cc18
-rw-r--r--chromium/base/process/process_metrics.cc8
-rw-r--r--chromium/base/process/process_metrics.h16
-rw-r--r--chromium/base/process/process_metrics_freebsd.cc12
-rw-r--r--chromium/base/process/process_metrics_ios.cc4
-rw-r--r--chromium/base/process/process_metrics_linux.cc28
-rw-r--r--chromium/base/process/process_metrics_mac.cc136
-rw-r--r--chromium/base/process/process_metrics_openbsd.cc17
-rw-r--r--chromium/base/process/process_metrics_posix.cc17
-rw-r--r--chromium/base/process/process_metrics_win.cc15
-rw-r--r--chromium/base/process/process_util_unittest.cc104
37 files changed, 697 insertions, 315 deletions
diff --git a/chromium/base/process/internal_linux.cc b/chromium/base/process/internal_linux.cc
index b1d1b6f174e..57a3ab4271a 100644
--- a/chromium/base/process/internal_linux.cc
+++ b/chromium/base/process/internal_linux.cc
@@ -115,13 +115,13 @@ void ParseProcStat(const std::string& contents, ProcStatMap* output) {
}
}
-int GetProcStatsFieldAsInt(const std::vector<std::string>& proc_stats,
- ProcStatsFields field_num) {
+int64 GetProcStatsFieldAsInt64(const std::vector<std::string>& proc_stats,
+ ProcStatsFields field_num) {
DCHECK_GE(field_num, VM_PPID);
CHECK_LT(static_cast<size_t>(field_num), proc_stats.size());
- int value;
- return StringToInt(proc_stats[field_num], &value) ? value : 0;
+ int64 value;
+ return StringToInt64(proc_stats[field_num], &value) ? value : 0;
}
size_t GetProcStatsFieldAsSizeT(const std::vector<std::string>& proc_stats,
@@ -133,15 +133,14 @@ size_t GetProcStatsFieldAsSizeT(const std::vector<std::string>& proc_stats,
return StringToSizeT(proc_stats[field_num], &value) ? value : 0;
}
-int ReadProcStatsAndGetFieldAsInt(pid_t pid,
- ProcStatsFields field_num) {
+int64 ReadProcStatsAndGetFieldAsInt64(pid_t pid, ProcStatsFields field_num) {
std::string stats_data;
if (!ReadProcStats(pid, &stats_data))
return 0;
std::vector<std::string> proc_stats;
if (!ParseProcStats(stats_data, &proc_stats))
return 0;
- return GetProcStatsFieldAsInt(proc_stats, field_num);
+ return GetProcStatsFieldAsInt64(proc_stats, field_num);
}
size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid,
diff --git a/chromium/base/process/internal_linux.h b/chromium/base/process/internal_linux.h
index 0cacd3f3a84..5fc33566607 100644
--- a/chromium/base/process/internal_linux.h
+++ b/chromium/base/process/internal_linux.h
@@ -63,19 +63,18 @@ enum ProcStatsFields {
// Reads the |field_num|th field from |proc_stats|. Returns 0 on failure.
// This version does not handle the first 3 values, since the first value is
// simply |pid|, and the next two values are strings.
-int GetProcStatsFieldAsInt(const std::vector<std::string>& proc_stats,
- ProcStatsFields field_num);
+int64 GetProcStatsFieldAsInt64(const std::vector<std::string>& proc_stats,
+ ProcStatsFields field_num);
-// Same as GetProcStatsFieldAsInt(), but for size_t values.
+// Same as GetProcStatsFieldAsInt64(), but for size_t values.
size_t GetProcStatsFieldAsSizeT(const std::vector<std::string>& proc_stats,
ProcStatsFields field_num);
-// Convenience wrapper around GetProcStatsFieldAsInt(), ParseProcStats() and
-// ReadProcStats(). See GetProcStatsFieldAsInt() for details.
-int ReadProcStatsAndGetFieldAsInt(pid_t pid,
- ProcStatsFields field_num);
+// Convenience wrapper around GetProcStatsFieldAsInt64(), ParseProcStats() and
+// ReadProcStats(). See GetProcStatsFieldAsInt64() for details.
+int64 ReadProcStatsAndGetFieldAsInt64(pid_t pid, ProcStatsFields field_num);
-// Same as ReadProcStatsAndGetFieldAsInt() but for size_t values.
+// Same as ReadProcStatsAndGetFieldAsInt64() but for size_t values.
size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid,
ProcStatsFields field_num);
diff --git a/chromium/base/process/kill_mac.cc b/chromium/base/process/kill_mac.cc
index 5ebca5d0076..1589a641a04 100644
--- a/chromium/base/process/kill_mac.cc
+++ b/chromium/base/process/kill_mac.cc
@@ -10,6 +10,7 @@
#include <sys/wait.h>
#include "base/file_util.h"
+#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
@@ -76,15 +77,13 @@ void WaitForChildToDie(pid_t child, int timeout) {
int result;
- int kq = HANDLE_EINTR(kqueue());
- if (kq == -1) {
+ ScopedFD kq(HANDLE_EINTR(kqueue()));
+ if (!kq.is_valid()) {
DPLOG(ERROR) << "kqueue()";
} else {
- file_util::ScopedFD auto_close_kq(&kq);
-
struct kevent change = {0};
EV_SET(&change, child, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
- result = HANDLE_EINTR(kevent(kq, &change, 1, NULL, 0, NULL));
+ result = HANDLE_EINTR(kevent(kq.get(), &change, 1, NULL, 0, NULL));
if (result == -1) {
if (errno != ESRCH) {
@@ -120,7 +119,7 @@ void WaitForChildToDie(pid_t child, int timeout) {
struct kevent event = {0};
while (remaining_delta.InMilliseconds() > 0) {
const struct timespec remaining_timespec = remaining_delta.ToTimeSpec();
- result = kevent(kq, NULL, 0, &event, 1, &remaining_timespec);
+ result = kevent(kq.get(), NULL, 0, &event, 1, &remaining_timespec);
if (result == -1 && errno == EINTR) {
remaining_delta = deadline - TimeTicks::Now();
result = 0;
diff --git a/chromium/base/process/kill_posix.cc b/chromium/base/process/kill_posix.cc
index 99d70d9ab55..18c14fd3a77 100644
--- a/chromium/base/process/kill_posix.cc
+++ b/chromium/base/process/kill_posix.cc
@@ -10,6 +10,7 @@
#include <unistd.h>
#include "base/file_util.h"
+#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/process/process_iterator.h"
@@ -21,11 +22,11 @@ namespace base {
namespace {
-int WaitpidWithTimeout(ProcessHandle handle,
- int64 wait_milliseconds,
- bool* success) {
+bool WaitpidWithTimeout(ProcessHandle handle,
+ int* status,
+ base::TimeDelta wait) {
// This POSIX version of this function only guarantees that we wait no less
- // than |wait_milliseconds| for the process to exit. The child process may
+ // than |wait| for the process to exit. The child process may
// exit sometime before the timeout has ended but we may still block for up
// to 256 milliseconds after the fact.
//
@@ -36,7 +37,7 @@ int WaitpidWithTimeout(ProcessHandle handle,
// affect other parts of the application and would be difficult to debug.
//
// Our strategy is to call waitpid() once up front to check if the process
- // has already exited, otherwise to loop for wait_milliseconds, sleeping for
+ // has already exited, otherwise to loop for |wait|, sleeping for
// at most 256 milliseconds each time using usleep() and then calling
// waitpid(). The amount of time we sleep starts out at 1 milliseconds, and
// we double it every 4 sleep cycles.
@@ -47,15 +48,18 @@ int WaitpidWithTimeout(ProcessHandle handle,
//
// This function is used primarily for unit tests, if we want to use it in
// the application itself it would probably be best to examine other routes.
- int status = -1;
- pid_t ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
+
+ if (wait.InMilliseconds() == base::kNoTimeout) {
+ return HANDLE_EINTR(waitpid(handle, status, 0)) > 0;
+ }
+
+ pid_t ret_pid = HANDLE_EINTR(waitpid(handle, status, WNOHANG));
static const int64 kMaxSleepInMicroseconds = 1 << 18; // ~256 milliseconds.
int64 max_sleep_time_usecs = 1 << 10; // ~1 milliseconds.
int64 double_sleep_time = 0;
// If the process hasn't exited yet, then sleep and try again.
- TimeTicks wakeup_time = TimeTicks::Now() +
- TimeDelta::FromMilliseconds(wait_milliseconds);
+ TimeTicks wakeup_time = TimeTicks::Now() + wait;
while (ret_pid == 0) {
TimeTicks now = TimeTicks::Now();
if (now > wakeup_time)
@@ -69,7 +73,7 @@ int WaitpidWithTimeout(ProcessHandle handle,
// usleep() will return 0 and set errno to EINTR on receipt of a signal
// such as SIGCHLD.
usleep(sleep_time_usecs);
- ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
+ ret_pid = HANDLE_EINTR(waitpid(handle, status, WNOHANG));
if ((max_sleep_time_usecs < kMaxSleepInMicroseconds) &&
(double_sleep_time++ % 4 == 0)) {
@@ -77,10 +81,7 @@ int WaitpidWithTimeout(ProcessHandle handle,
}
}
- if (success)
- *success = (ret_pid != -1);
-
- return status;
+ return ret_pid > 0;
}
TerminationStatus GetTerminationStatusImpl(ProcessHandle handle,
@@ -225,12 +226,8 @@ bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
bool WaitForExitCodeWithTimeout(ProcessHandle handle,
int* exit_code,
base::TimeDelta timeout) {
- bool waitpid_success = false;
- int status = WaitpidWithTimeout(handle, timeout.InMilliseconds(),
- &waitpid_success);
- if (status == -1)
- return false;
- if (!waitpid_success)
+ int status;
+ if (!WaitpidWithTimeout(handle, &status, timeout))
return false;
if (WIFSIGNALED(status)) {
*exit_code = -1;
@@ -273,16 +270,15 @@ static bool WaitForSingleNonChildProcess(ProcessHandle handle,
DCHECK_GT(handle, 0);
DCHECK(wait.InMilliseconds() == base::kNoTimeout || wait > base::TimeDelta());
- int kq = kqueue();
- if (kq == -1) {
+ ScopedFD kq(kqueue());
+ if (!kq.is_valid()) {
DPLOG(ERROR) << "kqueue";
return false;
}
- file_util::ScopedFD kq_closer(&kq);
struct kevent change = {0};
EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
- int result = HANDLE_EINTR(kevent(kq, &change, 1, NULL, 0, NULL));
+ int result = HANDLE_EINTR(kevent(kq.get(), &change, 1, NULL, 0, NULL));
if (result == -1) {
if (errno == ESRCH) {
// If the process wasn't found, it must be dead.
@@ -316,7 +312,7 @@ static bool WaitForSingleNonChildProcess(ProcessHandle handle,
remaining_timespec_ptr = &remaining_timespec;
}
- result = kevent(kq, NULL, 0, &event, 1, remaining_timespec_ptr);
+ result = kevent(kq.get(), NULL, 0, &event, 1, remaining_timespec_ptr);
if (result == -1 && errno == EINTR) {
if (!wait_forever) {
@@ -369,21 +365,10 @@ bool WaitForSingleProcess(ProcessHandle handle, base::TimeDelta wait) {
#endif // OS_MACOSX
}
- bool waitpid_success;
- int status = -1;
- if (wait.InMilliseconds() == base::kNoTimeout) {
- waitpid_success = (HANDLE_EINTR(waitpid(handle, &status, 0)) != -1);
- } else {
- status = WaitpidWithTimeout(
- handle, wait.InMilliseconds(), &waitpid_success);
- }
-
- if (status != -1) {
- DCHECK(waitpid_success);
- return WIFEXITED(status);
- } else {
+ int status;
+ if (!WaitpidWithTimeout(handle, &status, wait))
return false;
- }
+ return WIFEXITED(status);
}
bool CleanupProcesses(const FilePath::StringType& executable_name,
diff --git a/chromium/base/process/kill_win.cc b/chromium/base/process/kill_win.cc
index 99a7c661851..aaf3f30a936 100644
--- a/chromium/base/process/kill_win.cc
+++ b/chromium/base/process/kill_win.cc
@@ -96,9 +96,9 @@ bool KillProcess(ProcessHandle process, int exit_code, bool wait) {
if (result && wait) {
// The process may not end immediately due to pending I/O
if (WAIT_OBJECT_0 != WaitForSingleObject(process, 60 * 1000))
- DLOG_GETLASTERROR(ERROR) << "Error waiting for process exit";
+ DPLOG(ERROR) << "Error waiting for process exit";
} else if (!result) {
- DLOG_GETLASTERROR(ERROR) << "Unable to terminate process";
+ DPLOG(ERROR) << "Unable to terminate process";
}
return result;
}
@@ -111,7 +111,7 @@ bool KillProcessById(ProcessId process_id, int exit_code, bool wait) {
FALSE, // Don't inherit handle
process_id);
if (!process) {
- DLOG_GETLASTERROR(ERROR) << "Unable to open process " << process_id;
+ DPLOG(ERROR) << "Unable to open process " << process_id;
return false;
}
bool ret = KillProcess(process, exit_code, wait);
@@ -123,7 +123,7 @@ TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
DWORD tmp_exit_code = 0;
if (!::GetExitCodeProcess(handle, &tmp_exit_code)) {
- DLOG_GETLASTERROR(FATAL) << "GetExitCodeProcess() failed";
+ DPLOG(FATAL) << "GetExitCodeProcess() failed";
if (exit_code) {
// This really is a random number. We haven't received any
// information about the exit code, presumably because this
@@ -149,7 +149,7 @@ TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
}
if (wait_result == WAIT_FAILED) {
- DLOG_GETLASTERROR(ERROR) << "WaitForSingleObject() failed";
+ DPLOG(ERROR) << "WaitForSingleObject() failed";
} else {
DCHECK_EQ(WAIT_OBJECT_0, wait_result);
diff --git a/chromium/base/process/launch.cc b/chromium/base/process/launch.cc
index 0c9f3a88fef..a1c4d2159cb 100644
--- a/chromium/base/process/launch.cc
+++ b/chromium/base/process/launch.cc
@@ -20,11 +20,13 @@ LaunchOptions::LaunchOptions()
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)
#endif // OS_LINUX
#if defined(OS_CHROMEOS)
, ctrl_terminal_fd(-1)
@@ -36,4 +38,15 @@ LaunchOptions::LaunchOptions()
LaunchOptions::~LaunchOptions() {
}
+LaunchOptions LaunchOptionsForTest() {
+ LaunchOptions options;
+#if defined(OS_LINUX)
+ // To prevent accidental privilege sharing to an untrusted child, processes
+ // are started with PR_SET_NO_NEW_PRIVS. Do not set that here, since this
+ // new child will be used for testing only.
+ options.allow_new_privs = true;
+#endif
+ return options;
+}
+
} // namespace base
diff --git a/chromium/base/process/launch.h b/chromium/base/process/launch.h
index 336bfba16e9..261019b138f 100644
--- a/chromium/base/process/launch.h
+++ b/chromium/base/process/launch.h
@@ -7,7 +7,6 @@
#ifndef BASE_PROCESS_LAUNCH_H_
#define BASE_PROCESS_LAUNCH_H_
-#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -25,10 +24,10 @@
#include "base/win/scoped_handle.h"
#endif
-class CommandLine;
-
namespace base {
+class CommandLine;
+
#if defined(OS_WIN)
typedef std::vector<HANDLE> HandlesToInheritVector;
#endif
@@ -89,10 +88,15 @@ struct BASE_EXPORT LaunchOptions {
// job if any.
bool force_breakaway_from_job_;
#else
- // Set/unset environment variables. Empty (the default) means to inherit
- // the same environment. See AlterEnvironment().
+ // 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().
EnvironmentMap environ;
+ // Clear the environment for the new process before processing changes from
+ // |environ|.
+ bool clear_environ;
+
// 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
@@ -102,7 +106,7 @@ struct BASE_EXPORT LaunchOptions {
// 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::set<int>* maximize_rlimits;
+ const std::vector<int>* maximize_rlimits;
// If true, start the process in a new process group, instead of
// inheriting the parent's process group. The pgid of the child process
@@ -112,6 +116,10 @@ struct BASE_EXPORT LaunchOptions {
#if defined(OS_LINUX)
// If non-zero, start the process using clone(), using flags as provided.
int clone_flags;
+
+ // 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;
#endif // defined(OS_LINUX)
#if defined(OS_CHROMEOS)
@@ -120,6 +128,15 @@ struct BASE_EXPORT LaunchOptions {
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)
};
@@ -160,6 +177,16 @@ BASE_EXPORT bool LaunchProcess(const string16& cmdline,
const LaunchOptions& options,
win::ScopedHandle* process_handle);
+// Launches a process with elevated privileges. This does not behave exactly
+// like LaunchProcess as it uses ShellExecuteEx instead of CreateProcess to
+// create the process. This means the process will have elevated privileges
+// and thus some common operations like OpenProcess will fail. The process will
+// be available through the |process_handle| argument. Currently the only
+// supported LaunchOptions are |start_hidden| and |wait|.
+BASE_EXPORT bool LaunchElevatedProcess(const CommandLine& cmdline,
+ const LaunchOptions& options,
+ ProcessHandle* process_handle);
+
#elif defined(OS_POSIX)
// A POSIX-specific version of LaunchProcess that takes an argv array
// instead of a CommandLine. Useful for situations where you need to
@@ -232,8 +259,17 @@ 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
+// binary. This should not be called in production/released code.
+BASE_EXPORT LaunchOptions LaunchOptionsForTest();
+
} // namespace base
#endif // BASE_PROCESS_LAUNCH_H_
diff --git a/chromium/base/process/launch_mac.cc b/chromium/base/process/launch_mac.cc
index 176edca72ea..ce02475541e 100644
--- a/chromium/base/process/launch_mac.cc
+++ b/chromium/base/process/launch_mac.cc
@@ -5,6 +5,9 @@
#include "base/process/launch.h"
#include <mach/mach.h>
+#include <servers/bootstrap.h>
+
+#include "base/logging.h"
namespace base {
@@ -25,4 +28,21 @@ 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 8dc8f9e215d..78a3be47eb0 100644
--- a/chromium/base/process/launch_posix.cc
+++ b/chromium/base/process/launch_posix.cc
@@ -26,6 +26,7 @@
#include "base/debug/stack_trace.h"
#include "base/file_util.h"
#include "base/files/dir_reader_posix.h"
+#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/posix/eintr_wrapper.h"
@@ -37,6 +38,10 @@
#include "base/threading/platform_thread.h"
#include "base/threading/thread_restrictions.h"
+#if defined(OS_LINUX)
+#include <sys/prctl.h>
+#endif
+
#if defined(OS_CHROMEOS)
#include <sys/ioctl.h>
#endif
@@ -181,16 +186,16 @@ void ResetChildSignalHandlersToDefaults(void) {
} // anonymous namespace
-// A class to handle auto-closing of DIR*'s.
-class ScopedDIRClose {
- public:
+// Functor for |ScopedDIR| (below).
+struct ScopedDIRClose {
inline void operator()(DIR* x) const {
- if (x) {
+ if (x)
closedir(x);
- }
}
};
-typedef scoped_ptr_malloc<DIR, ScopedDIRClose> ScopedDIR;
+
+// Automatically closes |DIR*|s.
+typedef scoped_ptr<DIR, ScopedDIRClose> ScopedDIR;
#if defined(OS_LINUX)
static const char kFDDir[] = "/proc/self/fd";
@@ -207,7 +212,7 @@ static const char kFDDir[] = "/proc/self/fd";
#endif
void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
- // DANGER: no calls to malloc are allowed from now on:
+ // DANGER: no calls to malloc or locks are allowed from now on:
// http://crbug.com/36678
// Get the maximum number of FDs possible.
@@ -220,12 +225,13 @@ void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
const int fd = static_cast<int>(i);
if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
continue;
- InjectiveMultimap::const_iterator j;
- for (j = saved_mapping.begin(); j != saved_mapping.end(); j++) {
- if (fd == j->dest)
+ // Cannot use STL iterators here, since debug iterators use locks.
+ size_t j;
+ for (j = 0; j < saved_mapping.size(); j++) {
+ if (fd == saved_mapping[j].dest)
break;
}
- if (j != saved_mapping.end())
+ if (j < saved_mapping.size())
continue;
// Since we're just trying to close anything we can find,
@@ -249,12 +255,13 @@ void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
continue;
if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
continue;
- InjectiveMultimap::const_iterator i;
- for (i = saved_mapping.begin(); i != saved_mapping.end(); i++) {
- if (fd == i->dest)
+ // Cannot use STL iterators here, since debug iterators use locks.
+ size_t i;
+ for (i = 0; i < saved_mapping.size(); i++) {
+ if (fd == saved_mapping[i].dest)
break;
}
- if (i != saved_mapping.end())
+ if (i < saved_mapping.size())
continue;
if (fd == dir_fd)
continue;
@@ -285,8 +292,12 @@ bool LaunchProcess(const std::vector<std::string>& argv,
scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]);
scoped_ptr<char*[]> new_environ;
+ char* const empty_environ = NULL;
+ char* const* old_environ = GetEnvironment();
+ if (options.clear_environ)
+ old_environ = &empty_environ;
if (!options.environ.empty())
- new_environ = AlterEnvironment(GetEnvironment(), options.environ);
+ new_environ = AlterEnvironment(old_environ, options.environ);
sigset_t full_sigset;
sigfillset(&full_sigset);
@@ -318,6 +329,9 @@ bool LaunchProcess(const std::vector<std::string>& argv,
} else if (pid == 0) {
// Child process
+ // DANGER: no calls to malloc or locks are allowed from now on:
+ // http://crbug.com/36678
+
// DANGER: fork() rule: in the child, if you don't end up doing exec*(),
// you call _exit() instead of exit(). This is because _exit() does not
// call any previously-registered (in the parent) exit handlers, which
@@ -327,14 +341,13 @@ bool LaunchProcess(const std::vector<std::string>& argv,
// If a child process uses the readline library, the process block forever.
// In BSD like OSes including OS X it is safe to assign /dev/null as stdin.
// See http://crbug.com/56596.
- int null_fd = HANDLE_EINTR(open("/dev/null", O_RDONLY));
- if (null_fd < 0) {
+ base::ScopedFD null_fd(HANDLE_EINTR(open("/dev/null", O_RDONLY)));
+ if (!null_fd.is_valid()) {
RAW_LOG(ERROR, "Failed to open /dev/null");
_exit(127);
}
- file_util::ScopedFD null_fd_closer(&null_fd);
- int new_fd = HANDLE_EINTR(dup2(null_fd, STDIN_FILENO));
+ int new_fd = HANDLE_EINTR(dup2(null_fd.get(), STDIN_FILENO));
if (new_fd != STDIN_FILENO) {
RAW_LOG(ERROR, "Failed to dup /dev/null for stdin");
_exit(127);
@@ -356,16 +369,14 @@ bool LaunchProcess(const std::vector<std::string>& argv,
if (options.maximize_rlimits) {
// Some resource limits need to be maximal in this child.
- std::set<int>::const_iterator resource;
- for (resource = options.maximize_rlimits->begin();
- resource != options.maximize_rlimits->end();
- ++resource) {
+ for (size_t i = 0; i < options.maximize_rlimits->size(); ++i) {
+ const int resource = (*options.maximize_rlimits)[i];
struct rlimit limit;
- if (getrlimit(*resource, &limit) < 0) {
+ if (getrlimit(resource, &limit) < 0) {
RAW_LOG(WARNING, "getrlimit failed");
} else if (limit.rlim_cur < limit.rlim_max) {
limit.rlim_cur = limit.rlim_max;
- if (setrlimit(*resource, &limit) < 0) {
+ if (setrlimit(resource, &limit) < 0) {
RAW_LOG(WARNING, "setrlimit failed");
}
}
@@ -374,6 +385,8 @@ bool 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();
@@ -388,9 +401,6 @@ bool LaunchProcess(const std::vector<std::string>& argv,
memset(reinterpret_cast<void*>(malloc), 0xff, 8);
#endif // 0
- // DANGER: no calls to malloc are allowed from now on:
- // http://crbug.com/36678
-
#if defined(OS_CHROMEOS)
if (options.ctrl_terminal_fd >= 0) {
// Set process' controlling terminal.
@@ -406,15 +416,16 @@ bool LaunchProcess(const std::vector<std::string>& argv,
#endif // defined(OS_CHROMEOS)
if (options.fds_to_remap) {
- for (FileHandleMappingVector::const_iterator
- it = options.fds_to_remap->begin();
- it != options.fds_to_remap->end(); ++it) {
- fd_shuffle1.push_back(InjectionArc(it->first, it->second, false));
- fd_shuffle2.push_back(InjectionArc(it->first, it->second, false));
+ // Cannot use STL iterators here, since debug iterators use locks.
+ for (size_t i = 0; i < options.fds_to_remap->size(); ++i) {
+ const FileHandleMappingVector::value_type& value =
+ (*options.fds_to_remap)[i];
+ fd_shuffle1.push_back(InjectionArc(value.first, value.second, false));
+ fd_shuffle2.push_back(InjectionArc(value.first, value.second, false));
}
}
- if (!options.environ.empty())
+ if (!options.environ.empty() || options.clear_environ)
SetEnvironment(new_environ.get());
// fd_shuffle1 is mutated by this call because it cannot malloc.
@@ -423,6 +434,20 @@ bool LaunchProcess(const std::vector<std::string>& argv,
CloseSuperfluousFds(fd_shuffle2);
+ // Set NO_NEW_PRIVS by default. Since NO_NEW_PRIVS only exists in kernel
+ // 3.5+, do not check the return value of prctl here.
+#if defined(OS_LINUX)
+#ifndef PR_SET_NO_NEW_PRIVS
+#define PR_SET_NO_NEW_PRIVS 38
+#endif
+ if (!options.allow_new_privs) {
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) && errno != EINVAL) {
+ // Only log if the error is not EINVAL (i.e. not supported).
+ RAW_LOG(FATAL, "prctl(PR_SET_NO_NEW_PRIVS) failed");
+ }
+ }
+#endif
+
for (size_t i = 0; i < argv.size(); i++)
argv_cstr[i] = const_cast<char*>(argv[i].c_str());
argv_cstr[argv.size()] = NULL;
@@ -518,11 +543,12 @@ static GetAppOutputInternalResult GetAppOutputInternal(
return EXECUTE_FAILURE;
case 0: // child
{
+ // DANGER: no calls to malloc or locks are allowed from now on:
+ // http://crbug.com/36678
+
#if defined(OS_MACOSX)
RestoreDefaultExceptionHandler();
#endif
- // DANGER: no calls to malloc are allowed from now on:
- // http://crbug.com/36678
// Obscure fork() rule: in the child, if you don't end up doing exec*(),
// you call _exit() instead of exit(). This is because _exit() does not
@@ -544,8 +570,8 @@ static GetAppOutputInternalResult GetAppOutputInternal(
// Adding another element here? Remeber to increase the argument to
// reserve(), above.
- std::copy(fd_shuffle1.begin(), fd_shuffle1.end(),
- std::back_inserter(fd_shuffle2));
+ for (size_t i = 0; i < fd_shuffle1.size(); ++i)
+ fd_shuffle2.push_back(fd_shuffle1[i]);
if (!ShuffleFileDescriptors(&fd_shuffle1))
_exit(127);
diff --git a/chromium/base/process/launch_win.cc b/chromium/base/process/launch_win.cc
index 0c831cf7b4a..9e4db384ebb 100644
--- a/chromium/base/process/launch_win.cc
+++ b/chromium/base/process/launch_win.cc
@@ -6,6 +6,7 @@
#include <fcntl.h>
#include <io.h>
+#include <shellapi.h>
#include <windows.h>
#include <userenv.h>
#include <psapi.h>
@@ -22,6 +23,7 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/process/kill.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
#include "base/win/object_watcher.h"
#include "base/win/scoped_handle.h"
@@ -192,7 +194,8 @@ bool LaunchProcess(const string16& cmdline,
&temp_process_info);
DestroyEnvironmentBlock(enviroment_block);
if (!launched) {
- DPLOG(ERROR);
+ DPLOG(ERROR) << "Command line:" << std::endl << UTF16ToUTF8(cmdline)
+ << std::endl;;
return false;
}
} else {
@@ -200,7 +203,8 @@ bool LaunchProcess(const string16& cmdline,
const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL,
inherit_handles, flags, NULL, NULL,
startup_info, &temp_process_info)) {
- DPLOG(ERROR);
+ DPLOG(ERROR) << "Command line:" << std::endl << UTF16ToUTF8(cmdline)
+ << std::endl;;
return false;
}
}
@@ -239,6 +243,41 @@ bool LaunchProcess(const CommandLine& cmdline,
return rv;
}
+bool LaunchElevatedProcess(const CommandLine& cmdline,
+ const LaunchOptions& options,
+ ProcessHandle* process_handle) {
+ const string16 file = cmdline.GetProgram().value();
+ const string16 arguments = cmdline.GetArgumentsString();
+
+ SHELLEXECUTEINFO shex_info = {0};
+ shex_info.cbSize = sizeof(shex_info);
+ shex_info.fMask = SEE_MASK_NOCLOSEPROCESS;
+ shex_info.hwnd = GetActiveWindow();
+ shex_info.lpVerb = L"runas";
+ shex_info.lpFile = file.c_str();
+ shex_info.lpParameters = arguments.c_str();
+ shex_info.lpDirectory = NULL;
+ shex_info.nShow = options.start_hidden ? SW_HIDE : SW_SHOW;
+ shex_info.hInstApp = NULL;
+
+ if (!ShellExecuteEx(&shex_info)) {
+ DPLOG(ERROR);
+ return false;
+ }
+
+ if (options.wait)
+ WaitForSingleObject(shex_info.hProcess, INFINITE);
+
+ // If the caller wants the process handle give it to them, otherwise just
+ // close it. Closing it does not terminate the process.
+ if (process_handle)
+ *process_handle = shex_info.hProcess;
+ else
+ CloseHandle(shex_info.hProcess);
+
+ return true;
+}
+
bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags) {
JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {0};
limit_info.BasicLimitInformation.LimitFlags = limit_flags;
diff --git a/chromium/base/process/memory.cc b/chromium/base/process/memory.cc
new file mode 100644
index 00000000000..1dbc3630703
--- /dev/null
+++ b/chromium/base/process/memory.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 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/memory.h"
+
+namespace base {
+
+// Defined in memory_mac.mm for Mac.
+#if !defined(OS_MACOSX)
+
+bool UncheckedCalloc(size_t num_items, size_t size, void** result) {
+ const size_t alloc_size = num_items * size;
+
+ // Overflow check
+ if (size && ((alloc_size / size) != num_items)) {
+ *result = NULL;
+ return false;
+ }
+
+ if (!UncheckedMalloc(alloc_size, result))
+ return false;
+
+ memset(*result, 0, alloc_size);
+ return true;
+}
+
+#endif
+
+}
diff --git a/chromium/base/process/memory.h b/chromium/base/process/memory.h
index e6696cb8a70..100d9c72f43 100644
--- a/chromium/base/process/memory.h
+++ b/chromium/base/process/memory.h
@@ -14,6 +14,14 @@
#include <windows.h>
#endif
+#ifdef PVALLOC_AVAILABLE
+// Build config explicitly tells us whether or not pvalloc is available.
+#elif defined(LIBC_GLIBC) && !defined(USE_TCMALLOC)
+#define PVALLOC_AVAILABLE 1
+#else
+#define PVALLOC_AVAILABLE 0
+#endif
+
namespace base {
// Enables low fragmentation heap (LFH) for every heaps of this process. This
@@ -53,17 +61,21 @@ const int kMaxOomScore = 1000;
BASE_EXPORT bool AdjustOOMScore(ProcessId process, int score);
#endif
-#if defined(OS_MACOSX)
-// Very large images or svg canvases can cause huge mallocs. Skia
-// does tricks on tcmalloc-based systems to allow malloc to fail with
-// a NULL rather than hit the oom crasher. This replicates that for
-// OSX.
-//
-// IF YOU USE THIS WITHOUT CONSULTING YOUR FRIENDLY OSX DEVELOPER,
-// YOUR CODE IS LIKELY TO BE REVERTED. THANK YOU.
-BASE_EXPORT void* UncheckedMalloc(size_t size);
-BASE_EXPORT void* UncheckedCalloc(size_t num_items, size_t size);
-#endif // defined(OS_MACOSX)
+// 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.
+// This can be useful for huge and/or unpredictable size memory allocations.
+// Please only use this if you really handle the case when the allocation
+// fails. Doing otherwise would risk security.
+// These functions may still crash on OOM when running under memory tools,
+// specifically ASan and other sanitizers.
+// Return value tells whether the allocation succeeded. If it fails |result| is
+// set to NULL, otherwise it holds the memory address.
+BASE_EXPORT WARN_UNUSED_RESULT bool UncheckedMalloc(size_t size,
+ void** result);
+BASE_EXPORT WARN_UNUSED_RESULT bool UncheckedCalloc(size_t num_items,
+ size_t size,
+ void** result);
} // namespace base
diff --git a/chromium/base/process/memory_linux.cc b/chromium/base/process/memory_linux.cc
index 6bed68bd832..befd832d667 100644
--- a/chromium/base/process/memory_linux.cc
+++ b/chromium/base/process/memory_linux.cc
@@ -12,6 +12,22 @@
#include "base/process/internal_linux.h"
#include "base/strings/string_number_conversions.h"
+#if defined(USE_TCMALLOC)
+// Used by UncheckedMalloc. If tcmalloc is linked to the executable
+// this will be replaced by a strong symbol that actually implement
+// the semantics and don't call new handler in case the allocation fails.
+extern "C" {
+
+__attribute__((weak, visibility("default")))
+void* tc_malloc_skip_new_handler_weak(size_t size);
+
+void* tc_malloc_skip_new_handler_weak(size_t size) {
+ return malloc(size);
+}
+
+}
+#endif
+
namespace base {
size_t g_oom_size = 0U;
@@ -44,7 +60,9 @@ void* __libc_malloc(size_t size);
void* __libc_realloc(void* ptr, size_t size);
void* __libc_calloc(size_t nmemb, size_t size);
void* __libc_valloc(size_t size);
+#if PVALLOC_AVAILABLE == 1
void* __libc_pvalloc(size_t size);
+#endif
void* __libc_memalign(size_t alignment, size_t size);
// Overriding the system memory allocation functions:
@@ -99,7 +117,9 @@ void* __libc_memalign(size_t alignment, size_t size);
DIE_ON_OOM_1(malloc)
DIE_ON_OOM_1(valloc)
+#if PVALLOC_AVAILABLE == 1
DIE_ON_OOM_1(pvalloc)
+#endif
DIE_ON_OOM_2(calloc, size_t)
DIE_ON_OOM_2(realloc, void*)
@@ -157,9 +177,7 @@ bool AdjustOOMScore(ProcessId process, int score) {
DVLOG(1) << "Adjusting oom_score_adj of " << process << " to "
<< score_str;
int score_len = static_cast<int>(score_str.length());
- return (score_len == file_util::WriteFile(oom_file,
- score_str.c_str(),
- score_len));
+ return (score_len == WriteFile(oom_file, score_str.c_str(), score_len));
}
// If the oom_score_adj file doesn't exist, then we write the old
@@ -174,12 +192,22 @@ bool AdjustOOMScore(ProcessId process, int score) {
std::string score_str = IntToString(converted_score);
DVLOG(1) << "Adjusting oom_adj of " << process << " to " << score_str;
int score_len = static_cast<int>(score_str.length());
- return (score_len == file_util::WriteFile(oom_file,
- score_str.c_str(),
- score_len));
+ return (score_len == WriteFile(oom_file, score_str.c_str(), score_len));
}
return false;
}
+bool UncheckedMalloc(size_t size, void** result) {
+#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) || \
+ (!defined(LIBC_GLIBC) && !defined(USE_TCMALLOC))
+ *result = malloc(size);
+#elif defined(LIBC_GLIBC) && !defined(USE_TCMALLOC)
+ *result = __libc_malloc(size);
+#elif defined(USE_TCMALLOC)
+ *result = tc_malloc_skip_new_handler_weak(size);
+#endif
+ return *result != NULL;
+}
+
} // namespace base
diff --git a/chromium/base/process/memory_mac.mm b/chromium/base/process/memory_mac.mm
index 3e281cd8e3c..575e886a175 100644
--- a/chromium/base/process/memory_mac.mm
+++ b/chromium/base/process/memory_mac.mm
@@ -16,6 +16,7 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/mac/mac_util.h"
+#include "base/mac/mach_logging.h"
#include "base/scoped_clear_errno.h"
#include "third_party/apple_apsl/CFBase.h"
#include "third_party/apple_apsl/malloc.h"
@@ -222,10 +223,12 @@ void DeprotectMallocZone(ChromeMallocZone* default_zone,
reinterpret_cast<vm_region_info_t>(&info),
&count,
&unused);
- CHECK(result == KERN_SUCCESS);
+ MACH_CHECK(result == KERN_SUCCESS, result) << "mach_vm_region";
- result = mach_port_deallocate(mach_task_self(), unused);
- CHECK(result == KERN_SUCCESS);
+ // The kernel always returns a null object for VM_REGION_BASIC_INFO_64, but
+ // balance it with a deallocate in case this ever changes. See 10.9.2
+ // xnu-2422.90.20/osfmk/vm/vm_map.c vm_map_region.
+ mach_port_deallocate(mach_task_self(), unused);
// Does the region fully enclose the zone pointers? Possibly unwarranted
// simplification used: using the size of a full version 8 malloc zone rather
@@ -248,7 +251,7 @@ void DeprotectMallocZone(ChromeMallocZone* default_zone,
*reprotection_length,
false,
info.protection | VM_PROT_WRITE);
- CHECK(result == KERN_SUCCESS);
+ MACH_CHECK(result == KERN_SUCCESS, result) << "mach_vm_protect";
}
}
@@ -435,7 +438,7 @@ void oom_killer_new() {
// === Core Foundation CFAllocators ===
bool CanGetContextForCFAllocator() {
- return !base::mac::IsOSLaterThanMavericks_DontCallThis();
+ return !base::mac::IsOSLaterThanYosemite_DontCallThis();
}
CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) {
@@ -446,7 +449,8 @@ CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) {
return &our_allocator->_context;
} else if (base::mac::IsOSLion() ||
base::mac::IsOSMountainLion() ||
- base::mac::IsOSMavericks()) {
+ base::mac::IsOSMavericks() ||
+ base::mac::IsOSYosemite()) {
ChromeCFAllocatorLions* our_allocator =
const_cast<ChromeCFAllocatorLions*>(
reinterpret_cast<const ChromeCFAllocatorLions*>(allocator));
@@ -502,26 +506,42 @@ id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone)
} // namespace
-void* UncheckedMalloc(size_t size) {
+bool UncheckedMalloc(size_t size, void** result) {
if (g_old_malloc) {
#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true);
#endif // ARCH_CPU_32_BITS
- return g_old_malloc(malloc_default_zone(), size);
+ *result = g_old_malloc(malloc_default_zone(), size);
+ } else {
+ *result = malloc(size);
}
- return malloc(size);
+
+ return *result != NULL;
}
-void* UncheckedCalloc(size_t num_items, size_t size) {
+bool UncheckedCalloc(size_t num_items, size_t size, void** result) {
if (g_old_calloc) {
#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true);
#endif // ARCH_CPU_32_BITS
- return g_old_calloc(malloc_default_zone(), num_items, size);
+ *result = g_old_calloc(malloc_default_zone(), num_items, size);
+ } else {
+ *result = calloc(num_items, size);
}
- return calloc(num_items, size);
+
+ return *result != NULL;
+}
+
+void* UncheckedMalloc(size_t size) {
+ void* address;
+ return UncheckedMalloc(size, &address) ? address : NULL;
+}
+
+void* UncheckedCalloc(size_t num_items, size_t size) {
+ void* address;
+ return UncheckedCalloc(num_items, size, &address) ? address : NULL;
}
void EnableTerminationOnOutOfMemory() {
@@ -630,7 +650,7 @@ void EnableTerminationOnOutOfMemory() {
default_reprotection_length,
false,
default_reprotection_value);
- CHECK(result == KERN_SUCCESS);
+ MACH_CHECK(result == KERN_SUCCESS, result) << "mach_vm_protect";
}
if (purgeable_reprotection_start) {
@@ -639,7 +659,7 @@ void EnableTerminationOnOutOfMemory() {
purgeable_reprotection_length,
false,
purgeable_reprotection_value);
- CHECK(result == KERN_SUCCESS);
+ MACH_CHECK(result == KERN_SUCCESS, result) << "mach_vm_protect";
}
#endif
@@ -703,8 +723,9 @@ void EnableTerminationOnOutOfMemory() {
<< "Failed to get kCFAllocatorMallocZone allocation function.";
context->allocate = oom_killer_cfallocator_malloc_zone;
} else {
- NSLog(@"Internals of CFAllocator not known; out-of-memory failures via "
- "CFAllocator will not result in termination. http://crbug.com/45650");
+ DLOG(WARNING) << "Internals of CFAllocator not known; out-of-memory "
+ "failures via CFAllocator will not result in termination. "
+ "http://crbug.com/45650";
}
#endif
diff --git a/chromium/base/process/memory_unittest.cc b/chromium/base/process/memory_unittest.cc
index e5c759d5711..048c09d38c1 100644
--- a/chromium/base/process/memory_unittest.cc
+++ b/chromium/base/process/memory_unittest.cc
@@ -121,9 +121,7 @@ TEST(ProcessMemoryTest, MacMallocFailureDoesNotTerminate) {
buf = malloc(std::numeric_limits<size_t>::max() - (2 * PAGE_SIZE) - 1);
},
testing::KilledBySignal(SIGTRAP),
- "\\*\\*\\* error: can't allocate region.*"
- "(Terminating process due to a potential for future heap "
- "corruption){0}");
+ "\\*\\*\\* error: can't allocate region.*\\n?.*");
base::debug::Alias(buf);
}
@@ -143,8 +141,8 @@ TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) {
ASSERT_DEATH(free(buf), "attempting free on address which "
"was not malloc\\(\\)-ed");
#else
- ASSERT_DEATH(free(buf), "being freed.*"
- "\\*\\*\\* set a breakpoint in malloc_error_break to debug.*"
+ ASSERT_DEATH(free(buf), "being freed.*\\n?\\.*"
+ "\\*\\*\\* set a breakpoint in malloc_error_break to debug.*\\n?.*"
"Terminating process due to a potential for future heap corruption");
#endif // ARCH_CPU_64_BITS || defined(ADDRESS_SANITIZER)
}
@@ -154,13 +152,9 @@ TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) {
// Android doesn't implement set_new_handler, so we can't use the
// OutOfMemoryTest cases.
// OpenBSD does not support these tests either.
-// AddressSanitizer and ThreadSanitizer define the malloc()/free()/etc.
-// functions so that they don't crash if the program is out of memory, so the
-// OOM tests aren't supposed to work.
// TODO(vandebo) make this work on Windows too.
#if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && \
- !defined(OS_WIN) && \
- !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER)
+ !defined(OS_WIN)
#if defined(USE_TCMALLOC)
extern "C" {
@@ -168,14 +162,14 @@ int tc_set_new_mode(int mode);
}
#endif // defined(USE_TCMALLOC)
-class OutOfMemoryDeathTest : public testing::Test {
+class OutOfMemoryTest : public testing::Test {
public:
- OutOfMemoryDeathTest()
- : value_(NULL),
- // 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),
- signed_test_size_(std::numeric_limits<ssize_t>::max()) {
+ OutOfMemoryTest()
+ : value_(NULL),
+ // 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),
+ signed_test_size_(std::numeric_limits<ssize_t>::max()) {
}
#if defined(USE_TCMALLOC)
@@ -188,6 +182,14 @@ class OutOfMemoryDeathTest : public testing::Test {
}
#endif // defined(USE_TCMALLOC)
+ protected:
+ void* value_;
+ size_t test_size_;
+ ssize_t signed_test_size_;
+};
+
+class OutOfMemoryDeathTest : public OutOfMemoryTest {
+ public:
void SetUpInDeathAssert() {
// Must call EnableTerminationOnOutOfMemory() because that is called from
// chrome's main function and therefore hasn't been called yet.
@@ -196,10 +198,6 @@ class OutOfMemoryDeathTest : public testing::Test {
// should be done inside of the ASSERT_DEATH.
base::EnableTerminationOnOutOfMemory();
}
-
- void* value_;
- size_t test_size_;
- ssize_t signed_test_size_;
};
TEST_F(OutOfMemoryDeathTest, New) {
@@ -245,12 +243,15 @@ TEST_F(OutOfMemoryDeathTest, Valloc) {
}
#if defined(OS_LINUX)
+
+#if PVALLOC_AVAILABLE == 1
TEST_F(OutOfMemoryDeathTest, Pvalloc) {
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = pvalloc(test_size_);
}, "");
}
+#endif // PVALLOC_AVAILABLE == 1
TEST_F(OutOfMemoryDeathTest, Memalign) {
ASSERT_DEATH({
@@ -374,5 +375,54 @@ TEST_F(OutOfMemoryDeathTest, PsychoticallyBigObjCObject) {
#endif // !ARCH_CPU_64_BITS
#endif // OS_MACOSX
-#endif // !defined(OS_ANDROID) && !defined(OS_OPENBSD) &&
- // !defined(OS_WIN) && !defined(ADDRESS_SANITIZER)
+class OutOfMemoryHandledTest : public OutOfMemoryTest {
+ public:
+ static const size_t kSafeMallocSize = 512;
+ static const size_t kSafeCallocSize = 128;
+ static const size_t kSafeCallocItems = 4;
+
+ virtual void SetUp() {
+ OutOfMemoryTest::SetUp();
+
+ // We enable termination on OOM - just as Chrome does at early
+ // initialization - and test that UncheckedMalloc and UncheckedCalloc
+ // properly by-pass this in order to allow the caller to handle OOM.
+ base::EnableTerminationOnOutOfMemory();
+ }
+};
+
+// 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) {
+ EXPECT_TRUE(base::UncheckedMalloc(kSafeMallocSize, &value_));
+ EXPECT_TRUE(value_ != NULL);
+ free(value_);
+
+ EXPECT_FALSE(base::UncheckedMalloc(test_size_, &value_));
+ EXPECT_TRUE(value_ == NULL);
+}
+
+TEST_F(OutOfMemoryHandledTest, UncheckedCalloc) {
+ EXPECT_TRUE(base::UncheckedCalloc(1, kSafeMallocSize, &value_));
+ EXPECT_TRUE(value_ != NULL);
+ const char* bytes = static_cast<const char*>(value_);
+ for (size_t i = 0; i < kSafeMallocSize; ++i)
+ EXPECT_EQ(0, bytes[i]);
+ free(value_);
+
+ EXPECT_TRUE(
+ base::UncheckedCalloc(kSafeCallocItems, kSafeCallocSize, &value_));
+ EXPECT_TRUE(value_ != NULL);
+ bytes = static_cast<const char*>(value_);
+ for (size_t i = 0; i < (kSafeCallocItems * kSafeCallocSize); ++i)
+ EXPECT_EQ(0, bytes[i]);
+ free(value_);
+
+ 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)
diff --git a/chromium/base/process/memory_win.cc b/chromium/base/process/memory_win.cc
index c53a1be5395..668214ceaf0 100644
--- a/chromium/base/process/memory_win.cc
+++ b/chromium/base/process/memory_win.cc
@@ -82,4 +82,15 @@ 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.
+bool UncheckedMalloc(size_t size, void** result) {
+ *result = malloc(size);
+ return *result != NULL;
+}
+
} // namespace base
diff --git a/chromium/base/process/process_handle.h b/chromium/base/process/process_handle.h
index a37784275ea..6f8094ee80b 100644
--- a/chromium/base/process/process_handle.h
+++ b/chromium/base/process/process_handle.h
@@ -81,12 +81,10 @@ BASE_EXPORT bool GetProcessIntegrityLevel(ProcessHandle process,
IntegrityLevel* level);
#endif
-#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_BSD)
+#if defined(OS_POSIX)
// Returns the path to the executable of the given process.
BASE_EXPORT FilePath GetProcessExecutablePath(ProcessHandle process);
-#endif
-#if defined(OS_POSIX)
// Returns the ID for the parent of the given process.
BASE_EXPORT ProcessId GetParentProcessId(ProcessHandle process);
#endif
diff --git a/chromium/base/process/process_handle_freebsd.cc b/chromium/base/process/process_handle_freebsd.cc
index 8a0e9de8f2d..e465a85b7e0 100644
--- a/chromium/base/process/process_handle_freebsd.cc
+++ b/chromium/base/process/process_handle_freebsd.cc
@@ -6,6 +6,7 @@
#include <sys/sysctl.h>
#include <sys/types.h>
+#include <sys/user.h>
#include <unistd.h>
namespace base {
diff --git a/chromium/base/process/process_handle_linux.cc b/chromium/base/process/process_handle_linux.cc
index 0f7ccd348a8..6c5cd2fa182 100644
--- a/chromium/base/process/process_handle_linux.cc
+++ b/chromium/base/process/process_handle_linux.cc
@@ -11,7 +11,7 @@ namespace base {
ProcessId GetParentProcessId(ProcessHandle process) {
ProcessId pid =
- internal::ReadProcStatsAndGetFieldAsInt(process, internal::VM_PPID);
+ internal::ReadProcStatsAndGetFieldAsInt64(process, internal::VM_PPID);
if (pid)
return pid;
return -1;
diff --git a/chromium/base/process/process_handle_mac.cc b/chromium/base/process/process_handle_mac.cc
index 6cb8d686e4d..cbf0bc5c439 100644
--- a/chromium/base/process/process_handle_mac.cc
+++ b/chromium/base/process/process_handle_mac.cc
@@ -4,6 +4,7 @@
#include "base/process/process_handle.h"
+#include <libproc.h>
#include <sys/sysctl.h>
#include <sys/types.h>
@@ -24,4 +25,12 @@ ProcessId GetParentProcessId(ProcessHandle process) {
return info.kp_eproc.e_ppid;
}
+FilePath GetProcessExecutablePath(ProcessHandle process) {
+ char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
+ if (!proc_pidpath(process, pathbuf, sizeof(pathbuf)))
+ return FilePath();
+
+ return FilePath(pathbuf);
+}
+
} // namespace base
diff --git a/chromium/base/process/process_info_linux.cc b/chromium/base/process/process_info_linux.cc
index da34c180e8a..9ec23135bfc 100644
--- a/chromium/base/process/process_info_linux.cc
+++ b/chromium/base/process/process_info_linux.cc
@@ -15,8 +15,8 @@ namespace base {
//static
const Time CurrentProcessInfo::CreationTime() {
ProcessHandle pid = GetCurrentProcessHandle();
- int start_ticks = internal::ReadProcStatsAndGetFieldAsInt(
- pid, internal::VM_STARTTIME);
+ int64 start_ticks =
+ internal::ReadProcStatsAndGetFieldAsInt64(pid, internal::VM_STARTTIME);
DCHECK(start_ticks);
TimeDelta start_offset = internal::ClockTicksToTimeDelta(start_ticks);
Time boot_time = internal::GetBootTime();
diff --git a/chromium/base/process/process_info_mac.cc b/chromium/base/process/process_info_mac.cc
index ab8394b891d..b7cfdceda05 100644
--- a/chromium/base/process/process_info_mac.cc
+++ b/chromium/base/process/process_info_mac.cc
@@ -21,7 +21,7 @@ const Time CurrentProcessInfo::CreationTime() {
if (sysctl(mib, arraysize(mib), NULL, &len, NULL, 0) < 0)
return Time();
- scoped_ptr_malloc<struct kinfo_proc>
+ scoped_ptr<struct kinfo_proc, base::FreeDeleter>
proc(static_cast<struct kinfo_proc*>(malloc(len)));
if (sysctl(mib, arraysize(mib), proc.get(), &len, NULL, 0) < 0)
return Time();
diff --git a/chromium/base/process/process_iterator.h b/chromium/base/process/process_iterator.h
index aa8ba74aba0..aa2fc4148ad 100644
--- a/chromium/base/process/process_iterator.h
+++ b/chromium/base/process/process_iterator.h
@@ -20,8 +20,10 @@
#if defined(OS_WIN)
#include <windows.h>
#include <tlhelp32.h>
-#elif defined(OS_MACOSX) || defined(OS_BSD)
+#elif defined(OS_MACOSX) || defined(OS_OPENBSD)
#include <sys/sysctl.h>
+#elif defined(OS_FREEBSD)
+#include <sys/user.h>
#elif defined(OS_POSIX)
#include <dirent.h>
#endif
diff --git a/chromium/base/process/process_iterator_freebsd.cc b/chromium/base/process/process_iterator_freebsd.cc
index e8225b0054e..5b1e2ab09db 100644
--- a/chromium/base/process/process_iterator_freebsd.cc
+++ b/chromium/base/process/process_iterator_freebsd.cc
@@ -4,7 +4,9 @@
#include "base/process/process_iterator.h"
+#include <sys/types.h>
#include <sys/sysctl.h>
+#include <unistd.h>
#include "base/logging.h"
#include "base/strings/string_util.h"
diff --git a/chromium/base/process/process_iterator_linux.cc b/chromium/base/process/process_iterator_linux.cc
index 0587d7b88c5..8f746aa3391 100644
--- a/chromium/base/process/process_iterator_linux.cc
+++ b/chromium/base/process/process_iterator_linux.cc
@@ -121,8 +121,8 @@ bool ProcessIterator::CheckForNextProcess() {
}
entry_.pid_ = pid;
- entry_.ppid_ = GetProcStatsFieldAsInt(proc_stats, internal::VM_PPID);
- entry_.gid_ = GetProcStatsFieldAsInt(proc_stats, internal::VM_PGRP);
+ entry_.ppid_ = GetProcStatsFieldAsInt64(proc_stats, internal::VM_PPID);
+ entry_.gid_ = GetProcStatsFieldAsInt64(proc_stats, internal::VM_PGRP);
entry_.cmd_line_args_.assign(cmd_line_args.begin(), cmd_line_args.end());
entry_.exe_file_ = GetProcessExecutablePath(pid).BaseName().value();
return true;
diff --git a/chromium/base/process/process_iterator_mac.cc b/chromium/base/process/process_iterator_mac.cc
index 29daa2d489f..e35c2ae19ba 100644
--- a/chromium/base/process/process_iterator_mac.cc
+++ b/chromium/base/process/process_iterator_mac.cc
@@ -7,6 +7,7 @@
#include <errno.h>
#include <sys/sysctl.h>
#include <sys/types.h>
+#include <unistd.h>
#include "base/logging.h"
#include "base/strings/string_util.h"
diff --git a/chromium/base/process/process_linux.cc b/chromium/base/process/process_linux.cc
index b12e994848d..d92d7c30eee 100644
--- a/chromium/base/process/process_linux.cc
+++ b/chromium/base/process/process_linux.cc
@@ -14,6 +14,8 @@
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
+namespace base {
+
namespace {
const int kForegroundPriority = 0;
@@ -46,13 +48,13 @@ struct CGroups {
base::FilePath(base::StringPrintf(kControlPath, kForeground));
background_file =
base::FilePath(base::StringPrintf(kControlPath, kBackground));
- file_util::FileSystemType foreground_type;
- file_util::FileSystemType background_type;
+ base::FileSystemType foreground_type;
+ base::FileSystemType background_type;
enabled =
- file_util::GetFileSystemType(foreground_file, &foreground_type) &&
- file_util::GetFileSystemType(background_file, &background_type) &&
- foreground_type == file_util::FILE_SYSTEM_CGROUP &&
- background_type == file_util::FILE_SYSTEM_CGROUP;
+ base::GetFileSystemType(foreground_file, &foreground_type) &&
+ base::GetFileSystemType(background_file, &background_type) &&
+ foreground_type == FILE_SYSTEM_CGROUP &&
+ background_type == FILE_SYSTEM_CGROUP;
}
};
@@ -62,8 +64,6 @@ const int kBackgroundPriority = 5;
#endif
}
-namespace base {
-
bool Process::IsProcessBackgrounded() const {
DCHECK(process_);
@@ -95,7 +95,7 @@ bool Process::SetProcessBackgrounded(bool background) {
const base::FilePath file =
background ?
cgroups.Get().background_file : cgroups.Get().foreground_file;
- return file_util::WriteFile(file, pid.c_str(), pid.size()) > 0;
+ return base::WriteFile(file, pid.c_str(), pid.size()) > 0;
}
#endif // OS_CHROMEOS
diff --git a/chromium/base/process/process_metrics.cc b/chromium/base/process/process_metrics.cc
index 83289b8c78b..95fb87ddf62 100644
--- a/chromium/base/process/process_metrics.cc
+++ b/chromium/base/process/process_metrics.cc
@@ -4,6 +4,7 @@
#include "base/process/process_metrics.h"
+#include "base/logging.h"
#include "base/values.h"
namespace base {
@@ -50,4 +51,11 @@ double ProcessMetrics::GetPlatformIndependentCPUUsage() {
#endif
}
+#if !defined(OS_MACOSX)
+int ProcessMetrics::GetIdleWakeupsPerSecond() {
+ NOTIMPLEMENTED(); // http://crbug.com/20488
+ return 0;
+}
+#endif // !defined(OS_MACOSX)
+
} // namespace base
diff --git a/chromium/base/process/process_metrics.h b/chromium/base/process/process_metrics.h
index 560490a9b8c..d7a49ab5948 100644
--- a/chromium/base/process/process_metrics.h
+++ b/chromium/base/process/process_metrics.h
@@ -168,6 +168,10 @@ class BASE_EXPORT ProcessMetrics {
// CPU, this method returns 50.
double GetCPUUsage();
+ // Returns the number of average idle cpu wakeups per second since the last
+ // call.
+ int GetIdleWakeupsPerSecond();
+
// Same as GetCPUUsage(), but will return consistent values on all platforms
// (cancelling the Windows exception mentioned above) by returning a value in
// the range of 0 to (100 * numCPUCores) everywhere.
@@ -201,9 +205,13 @@ class BASE_EXPORT ProcessMetrics {
// Used to store the previous times and CPU usage counts so we can
// compute the CPU usage between calls.
- int64 last_time_;
+ TimeTicks last_cpu_time_;
int64 last_system_time_;
+ // Same thing for idle wakeups.
+ TimeTicks last_idle_wakeups_time_;
+ int64 last_absolute_idle_wakeups_;
+
#if !defined(OS_IOS)
#if defined(OS_MACOSX)
// Queries the port provider if it's set.
@@ -211,7 +219,7 @@ class BASE_EXPORT ProcessMetrics {
PortProvider* port_provider_;
#elif defined(OS_POSIX)
- // Jiffie count at the last_time_ we updated.
+ // Jiffie count at the last_cpu_time_ we updated.
int last_cpu_;
#endif // defined(OS_POSIX)
#endif // !defined(OS_IOS)
@@ -227,6 +235,10 @@ BASE_EXPORT size_t GetSystemCommitCharge();
// Returns the maximum number of file descriptors that can be open by a process
// at once. If the number is unavailable, a conservative best guess is returned.
size_t GetMaxFds();
+
+// Sets the file descriptor soft limit to |max_descriptors| or the OS hard
+// limit, whichever is lower.
+BASE_EXPORT void SetFdLimit(unsigned int max_descriptors);
#endif // defined(OS_POSIX)
#if defined(OS_LINUX) || defined(OS_ANDROID)
diff --git a/chromium/base/process/process_metrics_freebsd.cc b/chromium/base/process/process_metrics_freebsd.cc
index 019454cd81a..9d4149de2ad 100644
--- a/chromium/base/process/process_metrics_freebsd.cc
+++ b/chromium/base/process/process_metrics_freebsd.cc
@@ -4,11 +4,16 @@
#include "base/process/process_metrics.h"
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <unistd.h>
+
+#include "base/sys_info.h"
+
namespace base {
ProcessMetrics::ProcessMetrics(ProcessHandle process)
: process_(process),
- last_time_(0),
last_system_time_(0),
last_cpu_(0) {
processor_count_ = base::SysInfo::NumberOfProcessors();
@@ -81,11 +86,6 @@ double ProcessMetrics::GetCPUUsage() {
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_ };
size_t length = sizeof(info);
- struct timeval now;
- int retval = gettimeofday(&now, NULL);
- if (retval)
- return 0;
-
if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
return 0;
diff --git a/chromium/base/process/process_metrics_ios.cc b/chromium/base/process/process_metrics_ios.cc
index 94c671901b6..405c373c9fd 100644
--- a/chromium/base/process/process_metrics_ios.cc
+++ b/chromium/base/process/process_metrics_ios.cc
@@ -61,4 +61,8 @@ size_t GetMaxFds() {
return static_cast<size_t>(max_fds);
}
+void SetFdLimit(unsigned int max_descriptors) {
+ // Unimplemented.
+}
+
} // namespace base
diff --git a/chromium/base/process/process_metrics_linux.cc b/chromium/base/process/process_metrics_linux.cc
index afa88486a0b..0e12595f92e 100644
--- a/chromium/base/process/process_metrics_linux.cc
+++ b/chromium/base/process/process_metrics_linux.cc
@@ -36,7 +36,7 @@ static uint64 ReadFileToUint64(const base::FilePath file) {
std::string file_as_string;
if (!ReadFileToString(file, &file_as_string))
return 0;
- TrimWhitespaceASCII(file_as_string, TRIM_ALL, &file_as_string);
+ base::TrimWhitespaceASCII(file_as_string, base::TRIM_ALL, &file_as_string);
uint64 file_as_uint64 = 0;
if (!base::StringToUint64(file_as_string, &file_as_uint64))
return 0;
@@ -71,7 +71,8 @@ size_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) {
std::string value_str;
tokenizer.token_piece().CopyToString(&value_str);
std::string value_str_trimmed;
- TrimWhitespaceASCII(value_str, TRIM_ALL, &value_str_trimmed);
+ base::TrimWhitespaceASCII(value_str, base::TRIM_ALL,
+ &value_str_trimmed);
std::vector<std::string> split_value_str;
SplitString(value_str_trimmed, ' ', &split_value_str);
if (split_value_str.size() != 2 || split_value_str[1] != "kB") {
@@ -181,20 +182,16 @@ bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
}
double ProcessMetrics::GetCPUUsage() {
- struct timeval now;
- int retval = gettimeofday(&now, NULL);
- if (retval)
- return 0;
- int64 time = TimeValToMicroseconds(now);
+ TimeTicks time = TimeTicks::Now();
- if (last_time_ == 0) {
+ if (last_cpu_ == 0) {
// First call, just set the last values.
- last_time_ = time;
+ last_cpu_time_ = time;
last_cpu_ = GetProcessCPU(process_);
return 0;
}
- int64 time_delta = time - last_time_;
+ int64 time_delta = (time - last_cpu_time_).InMicroseconds();
DCHECK_NE(time_delta, 0);
if (time_delta == 0)
return 0;
@@ -209,7 +206,7 @@ double ProcessMetrics::GetCPUUsage() {
int percentage = 100 * (cpu_time - last_cpu_time).InSecondsF() /
TimeDelta::FromMicroseconds(time_delta).InSecondsF();
- last_time_ = time;
+ last_cpu_time_ = time;
last_cpu_ = cpu;
return percentage;
@@ -262,7 +259,6 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
ProcessMetrics::ProcessMetrics(ProcessHandle process)
: process_(process),
- last_time_(0),
last_system_time_(0),
last_cpu_(0) {
processor_count_ = base::SysInfo::NumberOfProcessors();
@@ -391,16 +387,16 @@ int ParseProcStatCPU(const std::string& input) {
if (proc_stats.size() <= internal::VM_STIME)
return -1;
- int utime = GetProcStatsFieldAsInt(proc_stats, internal::VM_UTIME);
- int stime = GetProcStatsFieldAsInt(proc_stats, internal::VM_STIME);
+ int utime = GetProcStatsFieldAsInt64(proc_stats, internal::VM_UTIME);
+ int stime = GetProcStatsFieldAsInt64(proc_stats, internal::VM_STIME);
return utime + stime;
}
const char kProcSelfExe[] = "/proc/self/exe";
int GetNumberOfThreads(ProcessHandle process) {
- return internal::ReadProcStatsAndGetFieldAsInt(process,
- internal::VM_NUMTHREADS);
+ return internal::ReadProcStatsAndGetFieldAsInt64(process,
+ internal::VM_NUMTHREADS);
}
namespace {
diff --git a/chromium/base/process/process_metrics_mac.cc b/chromium/base/process/process_metrics_mac.cc
index 048735ed36b..ada04e1427f 100644
--- a/chromium/base/process/process_metrics_mac.cc
+++ b/chromium/base/process/process_metrics_mac.cc
@@ -11,9 +11,27 @@
#include "base/containers/hash_tables.h"
#include "base/logging.h"
+#include "base/mac/mach_logging.h"
#include "base/mac/scoped_mach_port.h"
#include "base/sys_info.h"
+#if !defined(TASK_POWER_INFO)
+// Doesn't exist in the 10.6 or 10.7 SDKs.
+#define TASK_POWER_INFO 21
+struct task_power_info {
+ uint64_t total_user;
+ uint64_t total_system;
+ uint64_t task_interrupt_wakeups;
+ uint64_t task_platform_idle_wakeups;
+ uint64_t task_timer_wakeups_bin_1;
+ uint64_t task_timer_wakeups_bin_2;
+};
+typedef struct task_power_info task_power_info_data_t;
+typedef struct task_power_info *task_power_info_t;
+#define TASK_POWER_INFO_COUNT ((mach_msg_type_number_t) \
+ (sizeof (task_power_info_data_t) / sizeof (natural_t)))
+#endif
+
namespace base {
namespace {
@@ -99,7 +117,6 @@ size_t ProcessMetrics::GetPeakWorkingSetSize() const {
// shared_bytes is the size of shared resident memory.
bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes,
size_t* shared_bytes) {
- kern_return_t kr;
size_t private_pages_count = 0;
size_t shared_pages_count = 0;
@@ -136,22 +153,26 @@ bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes,
vm_region_top_info_data_t info;
mach_msg_type_number_t info_count = VM_REGION_TOP_INFO_COUNT;
mach_port_t object_name;
- kr = mach_vm_region(task,
- &address,
- &size,
- VM_REGION_TOP_INFO,
- (vm_region_info_t)&info,
- &info_count,
- &object_name);
+ kern_return_t kr = mach_vm_region(task,
+ &address,
+ &size,
+ VM_REGION_TOP_INFO,
+ reinterpret_cast<vm_region_info_t>(&info),
+ &info_count,
+ &object_name);
if (kr == KERN_INVALID_ADDRESS) {
// We're at the end of the address space.
break;
} else if (kr != KERN_SUCCESS) {
- DLOG(ERROR) << "Calling mach_vm_region failed with error: "
- << mach_error_string(kr);
+ MACH_DLOG(ERROR, kr) << "mach_vm_region";
return false;
}
+ // The kernel always returns a null object for VM_REGION_TOP_INFO, but
+ // balance it with a deallocate in case this ever changes. See 10.9.2
+ // xnu-2422.90.20/osfmk/vm/vm_map.c vm_map_region.
+ mach_port_deallocate(mach_task_self(), object_name);
+
if (IsAddressInSharedRegion(address, cpu_type) &&
info.share_mode != SM_PRIVATE)
continue;
@@ -179,18 +200,10 @@ bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes,
}
}
- vm_size_t page_size;
- kr = host_page_size(task, &page_size);
- if (kr != KERN_SUCCESS) {
- DLOG(ERROR) << "Failed to fetch host page size, error: "
- << mach_error_string(kr);
- return false;
- }
-
if (private_bytes)
- *private_bytes = private_pages_count * page_size;
+ *private_bytes = private_pages_count * PAGE_SIZE;
if (shared_bytes)
- *shared_bytes = shared_pages_count * page_size;
+ *shared_bytes = shared_pages_count * PAGE_SIZE;
return true;
}
@@ -218,16 +231,14 @@ double ProcessMetrics::GetCPUUsage() {
if (task == MACH_PORT_NULL)
return 0;
- kern_return_t kr;
-
// Libtop explicitly loops over the threads (libtop_pinfo_update_cpu_usage()
// in libtop.c), but this is more concise and gives the same results:
task_thread_times_info thread_info_data;
mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT;
- kr = task_info(task,
- TASK_THREAD_TIMES_INFO,
- reinterpret_cast<task_info_t>(&thread_info_data),
- &thread_info_count);
+ kern_return_t kr = task_info(task,
+ TASK_THREAD_TIMES_INFO,
+ reinterpret_cast<task_info_t>(&thread_info_data),
+ &thread_info_count);
if (kr != KERN_SUCCESS) {
// Most likely cause: |task| is a zombie.
return 0;
@@ -250,33 +261,69 @@ double ProcessMetrics::GetCPUUsage() {
timeradd(&user_timeval, &task_timeval, &task_timeval);
timeradd(&system_timeval, &task_timeval, &task_timeval);
- struct timeval now;
- int retval = gettimeofday(&now, NULL);
- if (retval)
- return 0;
-
- int64 time = TimeValToMicroseconds(now);
+ TimeTicks time = TimeTicks::Now();
int64 task_time = TimeValToMicroseconds(task_timeval);
- if ((last_system_time_ == 0) || (last_time_ == 0)) {
+ if (last_system_time_ == 0) {
// First call, just set the last values.
+ last_cpu_time_ = time;
last_system_time_ = task_time;
- last_time_ = time;
return 0;
}
int64 system_time_delta = task_time - last_system_time_;
- int64 time_delta = time - last_time_;
+ int64 time_delta = (time - last_cpu_time_).InMicroseconds();
DCHECK_NE(0U, time_delta);
if (time_delta == 0)
return 0;
+ last_cpu_time_ = time;
last_system_time_ = task_time;
- last_time_ = time;
return static_cast<double>(system_time_delta * 100.0) / time_delta;
}
+int ProcessMetrics::GetIdleWakeupsPerSecond() {
+ mach_port_t task = TaskForPid(process_);
+ if (task == MACH_PORT_NULL)
+ return 0;
+
+ task_power_info power_info_data;
+ mach_msg_type_number_t power_info_count = TASK_POWER_INFO_COUNT;
+ kern_return_t kr = task_info(task,
+ TASK_POWER_INFO,
+ reinterpret_cast<task_info_t>(&power_info_data),
+ &power_info_count);
+ if (kr != KERN_SUCCESS) {
+ // Most likely cause: |task| is a zombie, or this is on a pre-10.8.4 system
+ // where TASK_POWER_INFO isn't supported yet.
+ return 0;
+ }
+ uint64_t absolute_idle_wakeups = power_info_data.task_platform_idle_wakeups;
+
+ TimeTicks time = TimeTicks::Now();
+
+ if (last_absolute_idle_wakeups_ == 0) {
+ // First call, just set the last values.
+ last_idle_wakeups_time_ = time;
+ last_absolute_idle_wakeups_ = absolute_idle_wakeups;
+ return 0;
+ }
+
+ int64 wakeups_delta = absolute_idle_wakeups - last_absolute_idle_wakeups_;
+ int64 time_delta = (time - last_idle_wakeups_time_).InMicroseconds();
+ DCHECK_NE(0U, time_delta);
+ if (time_delta == 0)
+ return 0;
+
+ last_idle_wakeups_time_ = time;
+ last_absolute_idle_wakeups_ = absolute_idle_wakeups;
+
+ // Round to average wakeups per second.
+ const int kMicrosecondsPerSecond = 1000 * 1000;
+ return (wakeups_delta * kMicrosecondsPerSecond + time_delta/2) / time_delta;
+}
+
bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
return false;
}
@@ -284,8 +331,8 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
ProcessMetrics::ProcessMetrics(ProcessHandle process,
ProcessMetrics::PortProvider* port_provider)
: process_(process),
- last_time_(0),
last_system_time_(0),
+ last_absolute_idle_wakeups_(0),
port_provider_(port_provider) {
processor_count_ = SysInfo::NumberOfProcessors();
}
@@ -301,25 +348,18 @@ mach_port_t ProcessMetrics::TaskForPid(ProcessHandle process) const {
// Bytes committed by the system.
size_t GetSystemCommitCharge() {
- base::mac::ScopedMachPort host(mach_host_self());
+ base::mac::ScopedMachSendRight host(mach_host_self());
mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
vm_statistics_data_t data;
kern_return_t kr = host_statistics(host, HOST_VM_INFO,
reinterpret_cast<host_info_t>(&data),
&count);
- if (kr) {
- DLOG(WARNING) << "Failed to fetch host statistics.";
- return 0;
- }
-
- vm_size_t page_size;
- kr = host_page_size(host, &page_size);
- if (kr) {
- DLOG(ERROR) << "Failed to fetch host page size.";
+ if (kr != KERN_SUCCESS) {
+ MACH_DLOG(WARNING, kr) << "host_statistics";
return 0;
}
- return (data.active_count * page_size) / 1024;
+ return (data.active_count * PAGE_SIZE) / 1024;
}
} // namespace base
diff --git a/chromium/base/process/process_metrics_openbsd.cc b/chromium/base/process/process_metrics_openbsd.cc
index 36f607c0a9c..72927a1b578 100644
--- a/chromium/base/process/process_metrics_openbsd.cc
+++ b/chromium/base/process/process_metrics_openbsd.cc
@@ -106,22 +106,16 @@ static int GetProcessCPU(pid_t pid) {
}
double ProcessMetrics::GetCPUUsage() {
- struct timeval now;
+ TimeTicks time = TimeTicks::Now();
- int retval = gettimeofday(&now, NULL);
- if (retval)
- return 0;
-
- int64 time = TimeValToMicroseconds(now);
-
- if (last_time_ == 0) {
+ if (last_cpu_ == 0) {
// First call, just set the last values.
- last_time_ = time;
+ last_cpu_time_ = time;
last_cpu_ = GetProcessCPU(process_);
return 0;
}
- int64 time_delta = time - last_time_;
+ int64 time_delta = (time - last_cpu_time_).InMicroseconds();
DCHECK_NE(time_delta, 0);
if (time_delta == 0)
@@ -129,7 +123,7 @@ double ProcessMetrics::GetCPUUsage() {
int cpu = GetProcessCPU(process_);
- last_time_ = time;
+ last_cpu_time_ = time;
last_cpu_ = cpu;
double percentage = static_cast<double>((cpu * 100.0) / FSCALE);
@@ -139,7 +133,6 @@ double ProcessMetrics::GetCPUUsage() {
ProcessMetrics::ProcessMetrics(ProcessHandle process)
: process_(process),
- last_time_(0),
last_system_time_(0),
last_cpu_(0) {
diff --git a/chromium/base/process/process_metrics_posix.cc b/chromium/base/process/process_metrics_posix.cc
index 531f6a40d70..ea79d7348ff 100644
--- a/chromium/base/process/process_metrics_posix.cc
+++ b/chromium/base/process/process_metrics_posix.cc
@@ -52,4 +52,21 @@ size_t GetMaxFds() {
return static_cast<size_t>(max_fds);
}
+
+void SetFdLimit(unsigned int max_descriptors) {
+ struct rlimit limits;
+ if (getrlimit(RLIMIT_NOFILE, &limits) == 0) {
+ unsigned int new_limit = max_descriptors;
+ if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) {
+ new_limit = limits.rlim_max;
+ }
+ limits.rlim_cur = new_limit;
+ if (setrlimit(RLIMIT_NOFILE, &limits) != 0) {
+ PLOG(INFO) << "Failed to set file descriptor limit";
+ }
+ } else {
+ PLOG(INFO) << "Failed to get file descriptor limit";
+ }
+}
+
} // namespace base
diff --git a/chromium/base/process/process_metrics_win.cc b/chromium/base/process/process_metrics_win.cc
index f42ea86feb7..b1810b4c921 100644
--- a/chromium/base/process/process_metrics_win.cc
+++ b/chromium/base/process/process_metrics_win.cc
@@ -195,14 +195,11 @@ static uint64 FileTimeToUTC(const FILETIME& ftime) {
}
double ProcessMetrics::GetCPUUsage() {
- FILETIME now;
FILETIME creation_time;
FILETIME exit_time;
FILETIME kernel_time;
FILETIME user_time;
- GetSystemTimeAsFileTime(&now);
-
if (!GetProcessTimes(process_, &creation_time, &exit_time,
&kernel_time, &user_time)) {
// We don't assert here because in some cases (such as in the Task Manager)
@@ -212,17 +209,18 @@ double ProcessMetrics::GetCPUUsage() {
}
int64 system_time = (FileTimeToUTC(kernel_time) + FileTimeToUTC(user_time)) /
processor_count_;
- int64 time = FileTimeToUTC(now);
+ TimeTicks time = TimeTicks::Now();
- if ((last_system_time_ == 0) || (last_time_ == 0)) {
+ if (last_system_time_ == 0) {
// First call, just set the last values.
last_system_time_ = system_time;
- last_time_ = time;
+ last_cpu_time_ = time;
return 0;
}
int64 system_time_delta = system_time - last_system_time_;
- int64 time_delta = time - last_time_;
+ // FILETIME is in 100-nanosecond units, so this needs microseconds times 10.
+ int64 time_delta = (time - last_cpu_time_).InMicroseconds() * 10;
DCHECK_NE(0U, time_delta);
if (time_delta == 0)
return 0;
@@ -232,7 +230,7 @@ double ProcessMetrics::GetCPUUsage() {
time_delta);
last_system_time_ = system_time;
- last_time_ = time;
+ last_cpu_time_ = time;
return cpu;
}
@@ -269,7 +267,6 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
ProcessMetrics::ProcessMetrics(ProcessHandle process)
: process_(process),
processor_count_(base::SysInfo::NumberOfProcessors()),
- last_time_(0),
last_system_time_(0) {
}
diff --git a/chromium/base/process/process_util_unittest.cc b/chromium/base/process/process_util_unittest.cc
index 6bfc1d07388..20623a60e18 100644
--- a/chromium/base/process/process_util_unittest.cc
+++ b/chromium/base/process/process_util_unittest.cc
@@ -144,8 +144,9 @@ MULTIPROCESS_TEST_MAIN(SimpleChildProcess) {
return 0;
}
+// TODO(viettrungluu): This should be in a "MultiProcessTestTest".
TEST_F(ProcessUtilTest, SpawnChild) {
- base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false);
+ base::ProcessHandle handle = SpawnChild("SimpleChildProcess");
ASSERT_NE(base::kNullProcessHandle, handle);
EXPECT_TRUE(base::WaitForSingleProcess(
handle, TestTimeouts::action_max_timeout()));
@@ -161,7 +162,7 @@ TEST_F(ProcessUtilTest, KillSlowChild) {
const std::string signal_file =
ProcessUtilTest::GetSignalFilePath(kSignalFileSlow);
remove(signal_file.c_str());
- base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false);
+ base::ProcessHandle handle = SpawnChild("SlowChildProcess");
ASSERT_NE(base::kNullProcessHandle, handle);
SignalChildren(signal_file.c_str());
EXPECT_TRUE(base::WaitForSingleProcess(
@@ -175,7 +176,7 @@ TEST_F(ProcessUtilTest, DISABLED_GetTerminationStatusExit) {
const std::string signal_file =
ProcessUtilTest::GetSignalFilePath(kSignalFileSlow);
remove(signal_file.c_str());
- base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false);
+ base::ProcessHandle handle = SpawnChild("SlowChildProcess");
ASSERT_NE(base::kNullProcessHandle, handle);
int exit_code = 42;
@@ -198,7 +199,7 @@ TEST_F(ProcessUtilTest, DISABLED_GetTerminationStatusExit) {
TEST_F(ProcessUtilTest, GetProcId) {
base::ProcessId id1 = base::GetProcId(GetCurrentProcess());
EXPECT_NE(0ul, id1);
- base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false);
+ base::ProcessHandle handle = SpawnChild("SimpleChildProcess");
ASSERT_NE(base::kNullProcessHandle, handle);
base::ProcessId id2 = base::GetProcId(handle);
EXPECT_NE(0ul, id2);
@@ -233,8 +234,7 @@ MULTIPROCESS_TEST_MAIN(CrashingChildProcess) {
// This test intentionally crashes, so we don't need to run it under
// AddressSanitizer.
-// TODO(jschuh): crbug.com/175753 Fix this in Win64 bots.
-#if defined(ADDRESS_SANITIZER) || (defined(OS_WIN) && defined(ARCH_CPU_X86_64))
+#if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
#define MAYBE_GetTerminationStatusCrash DISABLED_GetTerminationStatusCrash
#else
#define MAYBE_GetTerminationStatusCrash GetTerminationStatusCrash
@@ -243,8 +243,7 @@ TEST_F(ProcessUtilTest, MAYBE_GetTerminationStatusCrash) {
const std::string signal_file =
ProcessUtilTest::GetSignalFilePath(kSignalFileCrash);
remove(signal_file.c_str());
- base::ProcessHandle handle = this->SpawnChild("CrashingChildProcess",
- false);
+ base::ProcessHandle handle = SpawnChild("CrashingChildProcess");
ASSERT_NE(base::kNullProcessHandle, handle);
int exit_code = 42;
@@ -291,8 +290,7 @@ TEST_F(ProcessUtilTest, GetTerminationStatusKill) {
const std::string signal_file =
ProcessUtilTest::GetSignalFilePath(kSignalFileKill);
remove(signal_file.c_str());
- base::ProcessHandle handle = this->SpawnChild("KilledChildProcess",
- false);
+ base::ProcessHandle handle = SpawnChild("KilledChildProcess");
ASSERT_NE(base::kNullProcessHandle, handle);
int exit_code = 42;
@@ -322,7 +320,7 @@ TEST_F(ProcessUtilTest, GetTerminationStatusKill) {
// Note: a platform may not be willing or able to lower the priority of
// a process. The calls to SetProcessBackground should be noops then.
TEST_F(ProcessUtilTest, SetProcessBackgrounded) {
- base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false);
+ base::ProcessHandle handle = SpawnChild("SimpleChildProcess");
base::Process process(handle);
int old_priority = process.GetPriority();
#if defined(OS_WIN)
@@ -393,8 +391,8 @@ TEST_F(ProcessUtilTest, LaunchAsUser) {
ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token));
base::LaunchOptions options;
options.as_user = token;
- EXPECT_TRUE(base::LaunchProcess(
- this->MakeCmdLine("SimpleChildProcess", false), options, NULL));
+ EXPECT_TRUE(base::LaunchProcess(MakeCmdLine("SimpleChildProcess"), options,
+ NULL));
}
static const char kEventToTriggerHandleSwitch[] = "event-to-trigger-handle";
@@ -430,7 +428,7 @@ TEST_F(ProcessUtilTest, InheritSpecifiedHandles) {
base::LaunchOptions options;
options.handles_to_inherit = &handles_to_inherit;
- CommandLine cmd_line = MakeCmdLine("TriggerEventChildProcess", false);
+ CommandLine cmd_line = MakeCmdLine("TriggerEventChildProcess");
cmd_line.AppendSwitchASCII(kEventToTriggerHandleSwitch,
base::Uint64ToString(reinterpret_cast<uint64>(event.handle())));
@@ -505,8 +503,10 @@ int ProcessUtilTest::CountOpenFDsInChild() {
base::FileHandleMappingVector fd_mapping_vec;
fd_mapping_vec.push_back(std::pair<int, int>(fds[1], kChildPipe));
- base::ProcessHandle handle = this->SpawnChild(
- "ProcessUtilsLeakFDChildProcess", fd_mapping_vec, false);
+ base::LaunchOptions options;
+ options.fds_to_remap = &fd_mapping_vec;
+ base::ProcessHandle handle =
+ SpawnChildWithOptions("ProcessUtilsLeakFDChildProcess", options);
CHECK(handle);
int ret = IGNORE_EINTR(close(fds[1]));
DPCHECK(ret == 0);
@@ -517,7 +517,7 @@ int ProcessUtilTest::CountOpenFDsInChild() {
HANDLE_EINTR(read(fds[0], &num_open_files, sizeof(num_open_files)));
CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(num_open_files)));
-#if defined(THREAD_SANITIZER) || defined(USE_HEAPCHECKER)
+#if defined(THREAD_SANITIZER)
// Compiler-based ThreadSanitizer makes this test slow.
CHECK(base::WaitForSingleProcess(handle, base::TimeDelta::FromSeconds(3)));
#else
@@ -562,15 +562,12 @@ TEST_F(ProcessUtilTest, MAYBE_FDRemapping) {
namespace {
-std::string TestLaunchProcess(const base::EnvironmentMap& env_changes,
+std::string TestLaunchProcess(const std::vector<std::string>& args,
+ const base::EnvironmentMap& env_changes,
+ const bool clear_environ,
const int clone_flags) {
- std::vector<std::string> args;
base::FileHandleMappingVector fds_to_remap;
- args.push_back(kPosixShell);
- args.push_back("-c");
- args.push_back("echo $BASE_TEST");
-
int fds[2];
PCHECK(pipe(fds) == 0);
@@ -578,6 +575,7 @@ std::string TestLaunchProcess(const base::EnvironmentMap& env_changes,
base::LaunchOptions options;
options.wait = true;
options.environ = env_changes;
+ options.clear_environ = clear_environ;
options.fds_to_remap = &fds_to_remap;
#if defined(OS_LINUX)
options.clone_flags = clone_flags;
@@ -589,7 +587,6 @@ std::string TestLaunchProcess(const base::EnvironmentMap& env_changes,
char buf[512];
const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
- PCHECK(n > 0);
PCHECK(IGNORE_EINTR(close(fds[0])) == 0);
@@ -609,37 +606,69 @@ const char kLargeString[] =
TEST_F(ProcessUtilTest, LaunchProcess) {
base::EnvironmentMap env_changes;
+ std::vector<std::string> echo_base_test;
+ echo_base_test.push_back(kPosixShell);
+ echo_base_test.push_back("-c");
+ echo_base_test.push_back("echo $BASE_TEST");
+
+ std::vector<std::string> print_env;
+ print_env.push_back("/usr/bin/env");
const int no_clone_flags = 0;
+ const bool no_clear_environ = false;
const char kBaseTest[] = "BASE_TEST";
env_changes[kBaseTest] = "bar";
- EXPECT_EQ("bar\n", TestLaunchProcess(env_changes, no_clone_flags));
+ EXPECT_EQ("bar\n",
+ TestLaunchProcess(
+ echo_base_test, env_changes, no_clear_environ, no_clone_flags));
env_changes.clear();
EXPECT_EQ(0, setenv(kBaseTest, "testing", 1 /* override */));
- EXPECT_EQ("testing\n", TestLaunchProcess(env_changes, no_clone_flags));
+ EXPECT_EQ("testing\n",
+ TestLaunchProcess(
+ echo_base_test, env_changes, no_clear_environ, no_clone_flags));
env_changes[kBaseTest] = std::string();
- EXPECT_EQ("\n", TestLaunchProcess(env_changes, no_clone_flags));
+ EXPECT_EQ("\n",
+ TestLaunchProcess(
+ echo_base_test, env_changes, no_clear_environ, no_clone_flags));
env_changes[kBaseTest] = "foo";
- EXPECT_EQ("foo\n", TestLaunchProcess(env_changes, no_clone_flags));
+ EXPECT_EQ("foo\n",
+ TestLaunchProcess(
+ echo_base_test, env_changes, no_clear_environ, no_clone_flags));
env_changes.clear();
EXPECT_EQ(0, setenv(kBaseTest, kLargeString, 1 /* override */));
EXPECT_EQ(std::string(kLargeString) + "\n",
- TestLaunchProcess(env_changes, no_clone_flags));
+ TestLaunchProcess(
+ echo_base_test, env_changes, no_clear_environ, no_clone_flags));
env_changes[kBaseTest] = "wibble";
- EXPECT_EQ("wibble\n", TestLaunchProcess(env_changes, no_clone_flags));
+ EXPECT_EQ("wibble\n",
+ TestLaunchProcess(
+ echo_base_test, env_changes, no_clear_environ, no_clone_flags));
#if defined(OS_LINUX)
// Test a non-trival value for clone_flags.
// Don't test on Valgrind as it has limited support for clone().
if (!RunningOnValgrind()) {
- EXPECT_EQ("wibble\n", TestLaunchProcess(env_changes, CLONE_FS | SIGCHLD));
+ EXPECT_EQ(
+ "wibble\n",
+ TestLaunchProcess(
+ echo_base_test, env_changes, no_clear_environ, CLONE_FS | SIGCHLD));
}
+
+ EXPECT_EQ(
+ "BASE_TEST=wibble\n",
+ TestLaunchProcess(
+ print_env, env_changes, true /* clear_environ */, no_clone_flags));
+ env_changes.clear();
+ EXPECT_EQ(
+ "",
+ TestLaunchProcess(
+ print_env, env_changes, true /* clear_environ */, no_clone_flags));
#endif
}
@@ -677,7 +706,13 @@ TEST_F(ProcessUtilTest, GetAppOutput) {
#endif // defined(OS_ANDROID)
}
-TEST_F(ProcessUtilTest, GetAppOutputRestricted) {
+// 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.
@@ -812,8 +847,7 @@ bool IsProcessDead(base::ProcessHandle child) {
}
TEST_F(ProcessUtilTest, DelayedTermination) {
- base::ProcessHandle child_process =
- SpawnChild("process_util_test_never_die", false);
+ base::ProcessHandle child_process = SpawnChild("process_util_test_never_die");
ASSERT_TRUE(child_process);
base::EnsureProcessTerminated(child_process);
base::WaitForSingleProcess(child_process, base::TimeDelta::FromSeconds(5));
@@ -832,7 +866,7 @@ MULTIPROCESS_TEST_MAIN(process_util_test_never_die) {
TEST_F(ProcessUtilTest, ImmediateTermination) {
base::ProcessHandle child_process =
- SpawnChild("process_util_test_die_immediately", false);
+ SpawnChild("process_util_test_die_immediately");
ASSERT_TRUE(child_process);
// Give it time to die.
sleep(2);