summaryrefslogtreecommitdiffstats
path: root/chromium/base/process
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-24 12:15:48 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:30:04 +0000
commitb014812705fc80bff0a5c120dfcef88f349816dc (patch)
tree25a2e2d9fa285f1add86aa333389a839f81a39ae /chromium/base/process
parent9f4560b1027ae06fdb497023cdcaf91b8511fa74 (diff)
BASELINE: Update Chromium to 68.0.3440.125
Change-Id: I23f19369e01f688e496f5bf179abb521ad73874f Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/base/process')
-rw-r--r--chromium/base/process/launch.h49
-rw-r--r--chromium/base/process/launch_fuchsia.cc36
-rw-r--r--chromium/base/process/launch_win.cc30
-rw-r--r--chromium/base/process/process_iterator.cc2
-rw-r--r--chromium/base/process/process_iterator.h8
-rw-r--r--chromium/base/process/process_linux.cc26
-rw-r--r--chromium/base/process/process_metrics.cc26
-rw-r--r--chromium/base/process/process_metrics.h24
-rw-r--r--chromium/base/process/process_metrics_freebsd.cc12
-rw-r--r--chromium/base/process/process_metrics_fuchsia.cc4
-rw-r--r--chromium/base/process/process_metrics_ios.cc6
-rw-r--r--chromium/base/process/process_metrics_linux.cc85
-rw-r--r--chromium/base/process/process_metrics_mac.cc30
-rw-r--r--chromium/base/process/process_metrics_openbsd.cc16
-rw-r--r--chromium/base/process/process_metrics_posix.cc5
-rw-r--r--chromium/base/process/process_metrics_unittest.cc14
-rw-r--r--chromium/base/process/process_metrics_win.cc36
-rw-r--r--chromium/base/process/process_unittest.cc2
-rw-r--r--chromium/base/process/process_util_unittest.cc292
19 files changed, 288 insertions, 415 deletions
diff --git a/chromium/base/process/launch.h b/chromium/base/process/launch.h
index 5ba92182e74..b4530b755a2 100644
--- a/chromium/base/process/launch.h
+++ b/chromium/base/process/launch.h
@@ -21,41 +21,38 @@
#include "base/strings/string_piece.h"
#include "build/build_config.h"
-#if defined(OS_POSIX)
-#include "base/posix/file_descriptor_shuffle.h"
-#elif defined(OS_WIN)
+#if defined(OS_WIN)
#include <windows.h>
-#endif
-
-#if defined(OS_FUCHSIA)
+#elif defined(OS_FUCHSIA)
#include <launchpad/launchpad.h>
#include <zircon/types.h>
#endif
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+#include "base/posix/file_descriptor_shuffle.h"
+#endif
+
namespace base {
class CommandLine;
#if defined(OS_WIN)
typedef std::vector<HANDLE> HandlesToInheritVector;
-#endif
-
-#if defined(OS_FUCHSIA)
+#elif defined(OS_FUCHSIA)
struct HandleToTransfer {
uint32_t id;
zx_handle_t handle;
};
typedef std::vector<HandleToTransfer> HandlesToTransferVector;
-#endif
-
-#if defined(OS_POSIX)
typedef std::vector<std::pair<int, int>> FileHandleMappingVector;
-#endif
+#elif defined(OS_POSIX)
+typedef std::vector<std::pair<int, int>> FileHandleMappingVector;
+#endif // defined(OS_WIN)
// Options for launching a subprocess that are passed to LaunchProcess().
// The default constructor constructs the object with default options.
struct BASE_EXPORT LaunchOptions {
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
// Delegate to be run in between fork and exec in the subprocess (see
// pre_exec_delegate below)
class BASE_EXPORT PreExecDelegate {
@@ -151,7 +148,11 @@ struct BASE_EXPORT LaunchOptions {
// CREATE_BREAKAWAY_FROM_JOB flag which allows it to breakout of the parent
// job if any.
bool force_breakaway_from_job_ = false;
-#else // !defined(OS_WIN)
+
+ // If set to true, permission to bring windows to the foreground is passed to
+ // the launched process if the current process has such permission.
+ bool grant_foreground_privilege = false;
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
// 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().
@@ -164,6 +165,7 @@ struct BASE_EXPORT LaunchOptions {
// Remap file descriptors according to the mapping of src_fd->dest_fd to
// propagate FDs into the child process.
FileHandleMappingVector fds_to_remap;
+#endif // defined(OS_WIN)
#if defined(OS_LINUX)
// If non-zero, start the process using clone(), using flags as provided.
@@ -207,10 +209,10 @@ struct BASE_EXPORT LaunchOptions {
// case child process is compromised.
// Cannot be combined with the clone flag LP_CLONE_FDIO_NAMESPACE, which is
// equivalent to cloning every path.
- std::vector<std::string> paths_to_map;
+ std::vector<FilePath> paths_to_map;
#endif // defined(OS_FUCHSIA)
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#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].
@@ -233,14 +235,13 @@ struct BASE_EXPORT LaunchOptions {
// inheriting the parent's process group. The pgid of the child process
// will be the same as its pid.
bool new_process_group = false;
-#endif // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#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 = -1;
#endif // defined(OS_CHROMEOS)
-#endif // !defined(OS_WIN)
};
// Launch a process via the command line |cmdline|.
@@ -281,7 +282,7 @@ BASE_EXPORT Process LaunchProcess(const string16& cmdline,
BASE_EXPORT Process LaunchElevatedProcess(const CommandLine& cmdline,
const LaunchOptions& options);
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
// A POSIX-specific version of LaunchProcess that takes an argv array
// instead of a CommandLine. Useful for situations where you need to
// control the command line arguments directly, but prefer the
@@ -293,7 +294,7 @@ BASE_EXPORT Process LaunchProcess(const std::vector<std::string>& argv,
// given multimap. Only call this function in a child process where you know
// that there aren't any other threads.
BASE_EXPORT void CloseSuperfluousFds(const InjectiveMultimap& saved_map);
-#endif // defined(OS_POSIX)
+#endif // defined(OS_WIN)
#if defined(OS_WIN)
// Set |job_object|'s JOBOBJECT_EXTENDED_LIMIT_INFORMATION
@@ -327,9 +328,7 @@ BASE_EXPORT bool GetAppOutputWithExitCode(const CommandLine& cl,
// instead of a CommandLine object. Useful for situations where you need to
// control the command line arguments directly.
BASE_EXPORT bool GetAppOutput(const StringPiece16& cl, std::string* output);
-#endif
-
-#if defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
// A POSIX-specific version of GetAppOutput that takes an argv array
// instead of a CommandLine. Useful for situations where you need to
// control the command line arguments directly.
@@ -340,7 +339,7 @@ BASE_EXPORT bool GetAppOutput(const std::vector<std::string>& argv,
// stderr.
BASE_EXPORT bool GetAppOutputAndError(const std::vector<std::string>& argv,
std::string* output);
-#endif // defined(OS_POSIX)
+#endif // defined(OS_WIN)
// If supported on the platform, and the user has sufficent rights, increase
// the current process's scheduling priority to a high priority.
diff --git a/chromium/base/process/launch_fuchsia.cc b/chromium/base/process/launch_fuchsia.cc
index d1edc473ede..3bc75809f72 100644
--- a/chromium/base/process/launch_fuchsia.cc
+++ b/chromium/base/process/launch_fuchsia.cc
@@ -62,7 +62,7 @@ bool GetAppOutputInternal(const CommandLine& cmd_line,
return process.WaitForExit(exit_code);
}
-bool MapPathsToLaunchpad(const std::vector<std::string> paths_to_map,
+bool MapPathsToLaunchpad(const std::vector<FilePath>& paths_to_map,
launchpad_t* lp) {
zx_status_t status;
@@ -72,29 +72,30 @@ bool MapPathsToLaunchpad(const std::vector<std::string> paths_to_map,
paths_c_str.reserve(paths_to_map.size());
for (size_t paths_idx = 0; paths_idx < paths_to_map.size(); ++paths_idx) {
- const std::string& next_path_str = paths_to_map[paths_idx];
-
- base::FilePath next_path(next_path_str);
- if (!DirectoryExists(next_path)) {
- DLOG(ERROR) << "Directory does not exist: " << next_path;
+ const FilePath& next_path = paths_to_map[paths_idx];
+ if (!PathExists(next_path)) {
+ DLOG(ERROR) << "Path does not exist: " << next_path;
return false;
}
- // Get a Zircon handle to the directory |next_path|.
- base::File dir(next_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
- base::ScopedPlatformFile scoped_fd(dir.TakePlatformFile());
+ File dir(next_path, File::FLAG_OPEN | File::FLAG_READ);
+ ScopedPlatformFile scoped_fd(dir.TakePlatformFile());
zx_handle_t handles[FDIO_MAX_HANDLES] = {};
uint32_t types[FDIO_MAX_HANDLES] = {};
- status = fdio_transfer_fd(scoped_fd.get(), 0, handles, types);
- if (status != ZX_OK) {
- ZX_LOG(ERROR, status) << "fdio_transfer_fd";
+ zx_status_t num_handles =
+ fdio_transfer_fd(scoped_fd.get(), 0, handles, types);
+ // fdio_transfer_fd() returns number of transferred handles, or negative
+ // error.
+ if (num_handles <= 0) {
+ DCHECK_LT(num_handles, 0);
+ ZX_LOG(ERROR, num_handles) << "fdio_transfer_fd";
return false;
}
ScopedZxHandle scoped_handle(handles[0]);
ignore_result(scoped_fd.release());
// Close the handles that we won't use.
- for (int i = 1; i < FDIO_MAX_HANDLES; ++i) {
+ for (int i = 1; i < num_handles; ++i) {
zx_handle_close(handles[i]);
}
@@ -107,14 +108,14 @@ bool MapPathsToLaunchpad(const std::vector<std::string> paths_to_map,
// Add the handle to the child's nametable.
// We use the macro PA_HND(..., <index>) to relate the handle to its
// position in the nametable, which is stored as an array of path strings
- // |paths_c_str|.
+ // |paths_str|.
status = launchpad_add_handle(lp, scoped_handle.release(),
PA_HND(PA_NS_DIR, paths_idx));
if (status != ZX_OK) {
ZX_LOG(ERROR, status) << "launchpad_add_handle";
return false;
}
- paths_c_str.push_back(next_path_str.c_str());
+ paths_c_str.push_back(next_path.value().c_str());
}
if (!paths_c_str.empty()) {
@@ -135,8 +136,7 @@ struct LaunchpadScopedTraits {
static void Free(launchpad_t* lp) { launchpad_destroy(lp); }
};
-using ScopedLaunchpad =
- base::ScopedGeneric<launchpad_t*, LaunchpadScopedTraits>;
+using ScopedLaunchpad = ScopedGeneric<launchpad_t*, LaunchpadScopedTraits>;
} // namespace
@@ -193,7 +193,7 @@ Process LaunchProcess(const std::vector<std::string>& argv,
environ_modifications["PWD"] = options.current_directory.value();
} else {
FilePath cwd;
- base::GetCurrentDirectory(&cwd);
+ GetCurrentDirectory(&cwd);
environ_modifications["PWD"] = cwd.value();
}
diff --git a/chromium/base/process/launch_win.cc b/chromium/base/process/launch_win.cc
index 0c798a88b45..0ae6820dfd9 100644
--- a/chromium/base/process/launch_win.cc
+++ b/chromium/base/process/launch_win.cc
@@ -20,7 +20,6 @@
#include "base/debug/activity_tracker.h"
#include "base/debug/stack_trace.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/process/kill.h"
#include "base/strings/utf_string_conversions.h"
@@ -256,9 +255,13 @@ Process LaunchProcess(const string16& cmdline,
startup_info->hStdError = options.stderr_handle;
}
- if (options.job_handle) {
+ const bool launch_suspended =
+ options.job_handle || options.grant_foreground_privilege;
+
+ if (launch_suspended)
flags |= CREATE_SUSPENDED;
+ if (options.job_handle) {
// If this code is run under a debugger, the launched process is
// automatically associated with a job object created by the debugger.
// The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this on Windows
@@ -307,18 +310,23 @@ Process LaunchProcess(const string16& cmdline,
}
base::win::ScopedProcessInformation process_info(temp_process_info);
- if (options.job_handle) {
- if (0 == AssignProcessToJobObject(options.job_handle,
- process_info.process_handle())) {
- DLOG(ERROR) << "Could not AssignProcessToObject.";
- Process scoped_process(process_info.TakeProcessHandle());
- scoped_process.Terminate(win::kProcessKilledExitCode, true);
- return Process();
- }
+ if (options.job_handle &&
+ !AssignProcessToJobObject(options.job_handle,
+ process_info.process_handle())) {
+ DPLOG(ERROR) << "Could not AssignProcessToObject";
+ Process scoped_process(process_info.TakeProcessHandle());
+ scoped_process.Terminate(win::kProcessKilledExitCode, true);
+ return Process();
+ }
- ResumeThread(process_info.thread_handle());
+ if (options.grant_foreground_privilege &&
+ !AllowSetForegroundWindow(GetProcId(process_info.process_handle()))) {
+ DPLOG(ERROR) << "Failed to grant foreground privilege to launched process";
}
+ if (launch_suspended)
+ ResumeThread(process_info.thread_handle());
+
if (options.wait)
WaitForSingleObject(process_info.process_handle(), INFINITE);
diff --git a/chromium/base/process/process_iterator.cc b/chromium/base/process/process_iterator.cc
index 013017f75b5..8b530a067ef 100644
--- a/chromium/base/process/process_iterator.cc
+++ b/chromium/base/process/process_iterator.cc
@@ -7,7 +7,7 @@
namespace base {
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
ProcessEntry::ProcessEntry() : pid_(0), ppid_(0), gid_(0) {}
ProcessEntry::ProcessEntry(const ProcessEntry& other) = default;
ProcessEntry::~ProcessEntry() = default;
diff --git a/chromium/base/process/process_iterator.h b/chromium/base/process/process_iterator.h
index 54a4ec610cb..b30ad412226 100644
--- a/chromium/base/process/process_iterator.h
+++ b/chromium/base/process/process_iterator.h
@@ -26,7 +26,7 @@
#include <sys/sysctl.h>
#elif defined(OS_FREEBSD)
#include <sys/user.h>
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
#include <dirent.h>
#endif
@@ -38,7 +38,7 @@ struct ProcessEntry : public PROCESSENTRY32 {
ProcessId parent_pid() const { return th32ParentProcessID; }
const wchar_t* exe_file() const { return szExeFile; }
};
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
struct BASE_EXPORT ProcessEntry {
ProcessEntry();
ProcessEntry(const ProcessEntry& other);
@@ -58,7 +58,7 @@ struct BASE_EXPORT ProcessEntry {
std::string exe_file_;
std::vector<std::string> cmd_line_args_;
};
-#endif // defined(OS_POSIX)
+#endif // defined(OS_WIN)
// Used to filter processes by process ID.
class ProcessFilter {
@@ -112,7 +112,7 @@ class BASE_EXPORT ProcessIterator {
#elif defined(OS_MACOSX) || defined(OS_BSD)
std::vector<kinfo_proc> kinfo_procs_;
size_t index_of_kinfo_proc_;
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
DIR* procfs_dir_;
#endif
ProcessEntry entry_;
diff --git a/chromium/base/process/process_linux.cc b/chromium/base/process/process_linux.cc
index 586766e7863..faf39afd4b8 100644
--- a/chromium/base/process/process_linux.cc
+++ b/chromium/base/process/process_linux.cc
@@ -8,7 +8,6 @@
#include <sys/resource.h>
#include "base/files/file_util.h"
-#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -75,19 +74,13 @@ struct CGroups {
const int kBackgroundPriority = 5;
#endif // defined(OS_CHROMEOS)
-struct CheckForNicePermission {
- CheckForNicePermission() : can_reraise_priority(false) {
- // We won't be able to raise the priority if we don't have the right rlimit.
- // The limit may be adjusted in /etc/security/limits.conf for PAM systems.
- struct rlimit rlim;
- if ((getrlimit(RLIMIT_NICE, &rlim) == 0) &&
- (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur)) {
- can_reraise_priority = true;
- }
- };
-
- bool can_reraise_priority;
-};
+bool CanReraisePriority() {
+ // We won't be able to raise the priority if we don't have the right rlimit.
+ // The limit may be adjusted in /etc/security/limits.conf for PAM systems.
+ struct rlimit rlim;
+ return (getrlimit(RLIMIT_NICE, &rlim) == 0) &&
+ (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur);
+}
} // namespace
@@ -98,9 +91,8 @@ bool Process::CanBackgroundProcesses() {
return true;
#endif // defined(OS_CHROMEOS)
- static LazyInstance<CheckForNicePermission>::DestructorAtExit
- check_for_nice_permission = LAZY_INSTANCE_INITIALIZER;
- return check_for_nice_permission.Get().can_reraise_priority;
+ static const bool can_reraise_priority = CanReraisePriority();
+ return can_reraise_priority;
}
bool Process::IsProcessBackgrounded() const {
diff --git a/chromium/base/process/process_metrics.cc b/chromium/base/process/process_metrics.cc
index 2eff3ea3d0c..c3a70633a3f 100644
--- a/chromium/base/process/process_metrics.cc
+++ b/chromium/base/process/process_metrics.cc
@@ -97,6 +97,32 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateCurrentProcessMetrics() {
#endif // !defined(OS_MACOSX) || defined(OS_IOS)
}
+#if !defined(OS_FREEBSD) || !defined(OS_POSIX)
+double ProcessMetrics::GetPlatformIndependentCPUUsage() {
+ TimeDelta cumulative_cpu = GetCumulativeCPUUsage();
+ TimeTicks time = TimeTicks::Now();
+
+ if (last_cumulative_cpu_.is_zero()) {
+ // First call, just set the last values.
+ last_cumulative_cpu_ = cumulative_cpu;
+ last_cpu_time_ = time;
+ return 0;
+ }
+
+ TimeDelta system_time_delta = cumulative_cpu - last_cumulative_cpu_;
+ TimeDelta time_delta = time - last_cpu_time_;
+ DCHECK(!time_delta.is_zero());
+ if (time_delta.is_zero())
+ return 0;
+
+ last_cumulative_cpu_ = cumulative_cpu;
+ last_cpu_time_ = time;
+
+ return 100.0 * system_time_delta.InMicrosecondsF() /
+ time_delta.InMicrosecondsF();
+}
+#endif
+
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
int ProcessMetrics::CalculateIdleWakeupsPerSecond(
uint64_t absolute_idle_wakeups) {
diff --git a/chromium/base/process/process_metrics.h b/chromium/base/process/process_metrics.h
index 3ae373f6963..0170a0c2db9 100644
--- a/chromium/base/process/process_metrics.h
+++ b/chromium/base/process/process_metrics.h
@@ -143,6 +143,12 @@ class BASE_EXPORT ProcessMetrics {
// first call, and an actual value only on the second and subsequent calls.
double GetPlatformIndependentCPUUsage();
+ // Returns the cumulative CPU usage across all threads of the process since
+ // process start. In case of multi-core processors, a process can consume CPU
+ // at a rate higher than wall-clock time, e.g. two cores at full utilization
+ // will result in a time delta of 2 seconds/per 1 wall-clock second.
+ TimeDelta GetCumulativeCPUUsage();
+
// Returns the number of average idle cpu wakeups per second since the last
// call.
int GetIdleWakeupsPerSecond();
@@ -219,8 +225,8 @@ class BASE_EXPORT ProcessMetrics {
// Used to store the previous times and CPU usage counts so we can
// compute the CPU usage between calls.
TimeTicks last_cpu_time_;
-#if defined(OS_WIN) || defined(OS_MACOSX)
- int64_t last_system_time_;
+#if !defined(OS_FREEBSD) || !defined(OS_POSIX)
+ TimeDelta last_cumulative_cpu_;
#endif
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
@@ -241,10 +247,7 @@ class BASE_EXPORT ProcessMetrics {
mach_port_t TaskForPid(ProcessHandle process) const;
PortProvider* port_provider_;
-#elif defined(OS_POSIX)
- // Jiffie count at the last_cpu_time_ we updated.
- int last_cpu_;
-#endif // defined(OS_POSIX)
+#endif // defined(OS_MACOSX)
#endif // !defined(OS_IOS)
DISALLOW_COPY_AND_ASSIGN(ProcessMetrics);
@@ -265,10 +268,11 @@ BASE_EXPORT size_t GetPageSize();
BASE_EXPORT size_t GetMaxFds();
#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
-// 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)
+// Increases the file descriptor soft limit to |max_descriptors| or the OS hard
+// limit, whichever is lower. If the limit is already higher than
+// |max_descriptors|, then nothing happens.
+BASE_EXPORT void IncreaseFdLimitTo(unsigned int max_descriptors);
+#endif // defined(OS_POSIX) && !defined(OS_FUCHSIA)
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
defined(OS_ANDROID) || defined(OS_AIX) || defined(OS_FUCHSIA)
diff --git a/chromium/base/process/process_metrics_freebsd.cc b/chromium/base/process/process_metrics_freebsd.cc
index 4dee9980292..a552c033dd8 100644
--- a/chromium/base/process/process_metrics_freebsd.cc
+++ b/chromium/base/process/process_metrics_freebsd.cc
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/process/process_metrics_iocounters.h"
+#include "base/stl_util.h"
namespace base {
@@ -27,15 +28,20 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
double ProcessMetrics::GetPlatformIndependentCPUUsage() {
struct kinfo_proc info;
- int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_ };
+ int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, process_};
size_t length = sizeof(info);
- if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
+ if (sysctl(mib, base::size(mib), &info, &length, NULL, 0) < 0)
return 0;
return (info.ki_pctcpu / FSCALE) * 100.0;
}
+TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
+ NOTREACHED();
+ return TimeDelta();
+}
+
bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
return false;
}
@@ -45,7 +51,7 @@ size_t GetSystemCommitCharge() {
unsigned long mem_total, mem_free, mem_inactive;
size_t length = sizeof(mem_total);
- if (sysctl(mib, arraysize(mib), &mem_total, &length, NULL, 0) < 0)
+ if (sysctl(mib, base::size(mib), &mem_total, &length, NULL, 0) < 0)
return 0;
length = sizeof(mem_free);
diff --git a/chromium/base/process/process_metrics_fuchsia.cc b/chromium/base/process/process_metrics_fuchsia.cc
index 3710c308408..a34dff73150 100644
--- a/chromium/base/process/process_metrics_fuchsia.cc
+++ b/chromium/base/process/process_metrics_fuchsia.cc
@@ -25,9 +25,9 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
return nullptr;
}
-double ProcessMetrics::GetPlatformIndependentCPUUsage() {
+TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
NOTIMPLEMENTED(); // TODO(fuchsia): https://crbug.com/706592.
- return 0.0;
+ return TimeDelta();
}
bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
diff --git a/chromium/base/process/process_metrics_ios.cc b/chromium/base/process/process_metrics_ios.cc
index 794304f7658..83fc3d69331 100644
--- a/chromium/base/process/process_metrics_ios.cc
+++ b/chromium/base/process/process_metrics_ios.cc
@@ -25,9 +25,9 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
return WrapUnique(new ProcessMetrics(process));
}
-double ProcessMetrics::GetPlatformIndependentCPUUsage() {
+TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
NOTIMPLEMENTED();
- return 0;
+ return TimeDelta();
}
size_t GetMaxFds() {
@@ -47,7 +47,7 @@ size_t GetMaxFds() {
return static_cast<size_t>(max_fds);
}
-void SetFdLimit(unsigned int max_descriptors) {
+void IncreaseFdLimitTo(unsigned int max_descriptors) {
// Unimplemented.
}
diff --git a/chromium/base/process/process_metrics_linux.cc b/chromium/base/process/process_metrics_linux.cc
index e13f9e7a643..16cde35368a 100644
--- a/chromium/base/process/process_metrics_linux.cc
+++ b/chromium/base/process/process_metrics_linux.cc
@@ -132,35 +132,17 @@ bool ReadProcStatusAndGetFieldAsUint64(pid_t pid,
// Get the total CPU of a single process. Return value is number of jiffies
// on success or -1 on error.
-int GetProcessCPU(pid_t pid) {
- // Use /proc/<pid>/task to find all threads and parse their /stat file.
- FilePath task_path = internal::GetProcPidDir(pid).Append("task");
-
- DIR* dir = opendir(task_path.value().c_str());
- if (!dir) {
- DPLOG(ERROR) << "opendir(" << task_path.value() << ")";
+int64_t GetProcessCPU(pid_t pid) {
+ std::string buffer;
+ std::vector<std::string> proc_stats;
+ if (!internal::ReadProcStats(pid, &buffer) ||
+ !internal::ParseProcStats(buffer, &proc_stats)) {
return -1;
}
- int total_cpu = 0;
- while (struct dirent* ent = readdir(dir)) {
- pid_t tid = internal::ProcDirSlotToPid(ent->d_name);
- if (!tid)
- continue;
-
- // Synchronously reading files in /proc does not hit the disk.
- ThreadRestrictions::ScopedAllowIO allow_io;
-
- std::string stat;
- FilePath stat_path =
- task_path.Append(ent->d_name).Append(internal::kStatFile);
- if (ReadFileToString(stat_path, &stat)) {
- int cpu = ParseProcStatCPU(stat);
- if (cpu > 0)
- total_cpu += cpu;
- }
- }
- closedir(dir);
+ int64_t total_cpu =
+ internal::GetProcStatsFieldAsInt64(proc_stats, internal::VM_UTIME) +
+ internal::GetProcStatsFieldAsInt64(proc_stats, internal::VM_STIME);
return total_cpu;
}
@@ -216,46 +198,8 @@ size_t ProcessMetrics::GetResidentSetSize() const {
getpagesize();
}
-double ProcessMetrics::GetPlatformIndependentCPUUsage() {
- TimeTicks time = TimeTicks::Now();
-
- if (last_cpu_ == 0) {
- // First call, just set the last values.
- last_cpu_time_ = time;
- last_cpu_ = GetProcessCPU(process_);
- return 0.0;
- }
-
- TimeDelta time_delta = time - last_cpu_time_;
- if (time_delta.is_zero()) {
- NOTREACHED();
- return 0.0;
- }
-
- int cpu = GetProcessCPU(process_);
-
- // The number of jiffies in the time period. Convert to percentage.
- // Note: this means this will go *over* 100 in the case where multiple threads
- // are together adding to more than one CPU's worth.
- TimeDelta cpu_time = internal::ClockTicksToTimeDelta(cpu);
- TimeDelta last_cpu_time = internal::ClockTicksToTimeDelta(last_cpu_);
-
- // If the number of threads running in the process has decreased since the
- // last time this function was called, |last_cpu_time| will be greater than
- // |cpu_time| which will result in a negative value in the below percentage
- // calculation. Prevent this by clamping to 0. https://crbug.com/546565.
- // This computation is known to be shaky when threads are destroyed between
- // "last" and "now", but for our current purposes, it's all right.
- double percentage = 0.0;
- if (last_cpu_time < cpu_time) {
- percentage = 100.0 * (cpu_time - last_cpu_time).InSecondsF() /
- time_delta.InSecondsF();
- }
-
- last_cpu_time_ = time;
- last_cpu_ = cpu;
-
- return percentage;
+TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
+ return internal::ClockTicksToTimeDelta(GetProcessCPU(process_));
}
// For the /proc/self/io file to exist, the Linux kernel must have
@@ -356,13 +300,12 @@ int ProcessMetrics::GetOpenFdSoftLimit() const {
return -1;
}
-ProcessMetrics::ProcessMetrics(ProcessHandle process)
- : process_(process),
#if defined(OS_LINUX) || defined(OS_AIX)
- last_absolute_idle_wakeups_(0),
+ProcessMetrics::ProcessMetrics(ProcessHandle process)
+ : process_(process), last_absolute_idle_wakeups_(0) {}
+#else
+ProcessMetrics::ProcessMetrics(ProcessHandle process) : process_(process) {}
#endif
- last_cpu_(0) {
-}
#if defined(OS_CHROMEOS)
// Private, Shared and Proportional working set sizes are obtained from
diff --git a/chromium/base/process/process_metrics_mac.cc b/chromium/base/process/process_metrics_mac.cc
index 148253f26d2..4ecf8cf1472 100644
--- a/chromium/base/process/process_metrics_mac.cc
+++ b/chromium/base/process/process_metrics_mac.cc
@@ -127,10 +127,10 @@ ProcessMetrics::TaskVMInfo ProcessMetrics::GetTaskVMInfo() const {
(r)->tv_usec = (a)->microseconds; \
} while (0)
-double ProcessMetrics::GetPlatformIndependentCPUUsage() {
+TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
mach_port_t task = TaskForPid(process_);
if (task == MACH_PORT_NULL)
- return 0;
+ return TimeDelta();
// Libtop explicitly loops over the threads (libtop_pinfo_update_cpu_usage()
// in libtop.c), but this is more concise and gives the same results:
@@ -142,12 +142,12 @@ double ProcessMetrics::GetPlatformIndependentCPUUsage() {
&thread_info_count);
if (kr != KERN_SUCCESS) {
// Most likely cause: |task| is a zombie.
- return 0;
+ return TimeDelta();
}
task_basic_info_64 task_info_data;
if (!GetTaskInfo(task, &task_info_data))
- return 0;
+ return TimeDelta();
/* Set total_time. */
// thread info contains live time...
@@ -162,26 +162,7 @@ double ProcessMetrics::GetPlatformIndependentCPUUsage() {
timeradd(&user_timeval, &task_timeval, &task_timeval);
timeradd(&system_timeval, &task_timeval, &task_timeval);
- TimeTicks time = TimeTicks::Now();
- int64_t task_time = TimeValToMicroseconds(task_timeval);
-
- if (last_system_time_ == 0) {
- // First call, just set the last values.
- last_cpu_time_ = time;
- last_system_time_ = task_time;
- return 0;
- }
-
- int64_t system_time_delta = task_time - last_system_time_;
- int64_t 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;
-
- return static_cast<double>(system_time_delta * 100.0) / time_delta;
+ return TimeDelta::FromMicroseconds(TimeValToMicroseconds(task_timeval));
}
int ProcessMetrics::GetPackageIdleWakeupsPerSecond() {
@@ -220,7 +201,6 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
ProcessMetrics::ProcessMetrics(ProcessHandle process,
PortProvider* port_provider)
: process_(process),
- last_system_time_(0),
last_absolute_idle_wakeups_(0),
last_absolute_package_idle_wakeups_(0),
port_provider_(port_provider) {}
diff --git a/chromium/base/process/process_metrics_openbsd.cc b/chromium/base/process/process_metrics_openbsd.cc
index 3bb1ac5c3bb..509ed0b28ab 100644
--- a/chromium/base/process/process_metrics_openbsd.cc
+++ b/chromium/base/process/process_metrics_openbsd.cc
@@ -45,29 +45,25 @@ static int GetProcessCPU(pid_t pid) {
double ProcessMetrics::GetPlatformIndependentCPUUsage() {
TimeTicks time = TimeTicks::Now();
- if (last_cpu_ == 0) {
+ if (last_cpu_time_.is_zero()) {
// First call, just set the last values.
last_cpu_time_ = time;
- last_cpu_ = GetProcessCPU(process_);
return 0;
}
- int64_t time_delta = (time - last_cpu_time_).InMicroseconds();
- DCHECK_NE(time_delta, 0);
-
- if (time_delta == 0)
- return 0;
-
int cpu = GetProcessCPU(process_);
last_cpu_time_ = time;
- last_cpu_ = cpu;
-
double percentage = static_cast<double>((cpu * 100.0) / FSCALE);
return percentage;
}
+TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
+ NOTREACHED();
+ return TimeDelta();
+}
+
ProcessMetrics::ProcessMetrics(ProcessHandle process)
: process_(process),
last_cpu_(0) {}
diff --git a/chromium/base/process/process_metrics_posix.cc b/chromium/base/process/process_metrics_posix.cc
index e2d2c62e1e5..a09bbf2c56e 100644
--- a/chromium/base/process/process_metrics_posix.cc
+++ b/chromium/base/process/process_metrics_posix.cc
@@ -71,11 +71,12 @@ size_t GetMaxFds() {
return static_cast<size_t>(max_fds);
}
-
-void SetFdLimit(unsigned int max_descriptors) {
+void IncreaseFdLimitTo(unsigned int max_descriptors) {
struct rlimit limits;
if (getrlimit(RLIMIT_NOFILE, &limits) == 0) {
unsigned int new_limit = max_descriptors;
+ if (max_descriptors <= limits.rlim_cur)
+ return;
if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) {
new_limit = limits.rlim_max;
}
diff --git a/chromium/base/process/process_metrics_unittest.cc b/chromium/base/process/process_metrics_unittest.cc
index cb952950286..eba543a6187 100644
--- a/chromium/base/process/process_metrics_unittest.cc
+++ b/chromium/base/process/process_metrics_unittest.cc
@@ -33,7 +33,7 @@
namespace base {
namespace debug {
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN)
namespace {
void BusyWork(std::vector<std::string>* vec) {
@@ -321,7 +321,7 @@ TEST_F(SystemMetricsTest, ParseVmstat) {
}
#endif // defined(OS_LINUX) || defined(OS_ANDROID)
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN)
// Test that ProcessMetrics::GetPlatformIndependentCPUUsage() doesn't return
// negative values when the number of threads running on the process decreases
@@ -352,15 +352,25 @@ TEST_F(SystemMetricsTest, TestNoNegativeCpuUsage) {
thread2.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec2));
thread3.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec3));
+ TimeDelta prev_cpu_usage = metrics->GetCumulativeCPUUsage();
+ EXPECT_GE(prev_cpu_usage, TimeDelta());
EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
thread1.Stop();
+ TimeDelta current_cpu_usage = metrics->GetCumulativeCPUUsage();
+ EXPECT_GE(current_cpu_usage, prev_cpu_usage);
+ prev_cpu_usage = current_cpu_usage;
EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
thread2.Stop();
+ current_cpu_usage = metrics->GetCumulativeCPUUsage();
+ EXPECT_GE(current_cpu_usage, prev_cpu_usage);
+ prev_cpu_usage = current_cpu_usage;
EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
thread3.Stop();
+ current_cpu_usage = metrics->GetCumulativeCPUUsage();
+ EXPECT_GE(current_cpu_usage, prev_cpu_usage);
EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
}
diff --git a/chromium/base/process/process_metrics_win.cc b/chromium/base/process/process_metrics_win.cc
index faabdbf63a2..18ef58a725c 100644
--- a/chromium/base/process/process_metrics_win.cc
+++ b/chromium/base/process/process_metrics_win.cc
@@ -128,14 +128,7 @@ class WorkingSetInformationBuffer {
} // namespace
-static uint64_t FileTimeToUTC(const FILETIME& ftime) {
- LARGE_INTEGER li;
- li.LowPart = ftime.dwLowDateTime;
- li.HighPart = ftime.dwHighDateTime;
- return li.QuadPart;
-}
-
-double ProcessMetrics::GetPlatformIndependentCPUUsage() {
+TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
FILETIME creation_time;
FILETIME exit_time;
FILETIME kernel_time;
@@ -146,37 +139,18 @@ double ProcessMetrics::GetPlatformIndependentCPUUsage() {
// We don't assert here because in some cases (such as in the Task Manager)
// we may call this function on a process that has just exited but we have
// not yet received the notification.
- return 0;
- }
- int64_t system_time = FileTimeToUTC(kernel_time) + FileTimeToUTC(user_time);
- TimeTicks time = TimeTicks::Now();
-
- if (last_system_time_ == 0) {
- // First call, just set the last values.
- last_system_time_ = system_time;
- last_cpu_time_ = time;
- return 0;
+ return TimeDelta();
}
- int64_t system_time_delta = system_time - last_system_time_;
- // FILETIME is in 100-nanosecond units, so this needs microseconds times 10.
- int64_t time_delta = (time - last_cpu_time_).InMicroseconds() * 10;
- DCHECK_NE(0U, time_delta);
- if (time_delta == 0)
- return 0;
-
-
- last_system_time_ = system_time;
- last_cpu_time_ = time;
-
- return static_cast<double>(system_time_delta * 100) / time_delta;
+ return TimeDelta::FromFileTime(kernel_time) +
+ TimeDelta::FromFileTime(user_time);
}
bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
return GetProcessIoCounters(process_.Get(), io_counters) != FALSE;
}
-ProcessMetrics::ProcessMetrics(ProcessHandle process) : last_system_time_(0) {
+ProcessMetrics::ProcessMetrics(ProcessHandle process) {
if (process) {
HANDLE duplicate_handle = INVALID_HANDLE_VALUE;
BOOL result = ::DuplicateHandle(::GetCurrentProcess(), process,
diff --git a/chromium/base/process/process_unittest.cc b/chromium/base/process/process_unittest.cc
index f5058ebc504..9f678d141a1 100644
--- a/chromium/base/process/process_unittest.cc
+++ b/chromium/base/process/process_unittest.cc
@@ -146,7 +146,7 @@ TEST_F(ProcessTest, Terminate) {
EXPECT_NE(TERMINATION_STATUS_STILL_RUNNING,
GetTerminationStatus(process.Handle(), &exit_code));
-#if !defined(OS_POSIX)
+#if !defined(OS_POSIX) && !defined(OS_FUCHSIA)
// The POSIX implementation actually ignores the exit_code.
EXPECT_EQ(kExpectedExitCode, exit_code);
#endif
diff --git a/chromium/base/process/process_util_unittest.cc b/chromium/base/process/process_util_unittest.cc
index a2a5e9fc553..89466695fcf 100644
--- a/chromium/base/process/process_util_unittest.cc
+++ b/chromium/base/process/process_util_unittest.cc
@@ -9,7 +9,6 @@
#include <limits>
-#include "base/base_paths_fuchsia.h"
#include "base/command_line.h"
#include "base/debug/alias.h"
#include "base/debug/stack_trace.h"
@@ -44,14 +43,14 @@
#include <sys/syscall.h>
#endif
#if defined(OS_POSIX)
+#include <sys/resource.h>
+#endif
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <signal.h>
-#if !defined(OS_FUCHSIA)
-#include <sys/resource.h>
-#endif
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -72,6 +71,7 @@
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>
+#include "base/base_paths_fuchsia.h"
#endif
namespace base {
@@ -80,24 +80,20 @@ namespace {
const char kSignalFileSlow[] = "SlowChildProcess.die";
const char kSignalFileKill[] = "KilledChildProcess.die";
+const char kTestHelper[] = "test_child_process";
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
const char kSignalFileTerm[] = "TerminatedChildProcess.die";
+#endif
-#if defined(OS_ANDROID)
-const char kShellPath[] = "/system/bin/sh";
-#elif defined(OS_FUCHSIA)
-const char kShellPath[] = "/boot/bin/sh";
-const char kSignalFileClone[] = "/tmp/ClonedTmpDir.die";
-#else
-const char kShellPath[] = "/bin/sh";
+#if defined(OS_FUCHSIA)
+const char kSignalFileClone[] = "ClonedTmpDir.die";
#endif
-#endif // defined(OS_POSIX)
#if defined(OS_WIN)
const int kExpectedStillRunningExitCode = 0x102;
const int kExpectedKilledExitCode = 1;
-#else
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
const int kExpectedStillRunningExitCode = 0;
#endif
@@ -144,23 +140,31 @@ const int kSuccess = 0;
class ProcessUtilTest : public MultiProcessTest {
public:
-#if defined(OS_POSIX)
+ void SetUp() override {
+ ASSERT_TRUE(PathService::Get(DIR_ASSETS, &test_helper_path_));
+ test_helper_path_ = test_helper_path_.AppendASCII(kTestHelper);
+ }
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
// Spawn a child process that counts how many file descriptors are open.
int CountOpenFDsInChild();
#endif
// Converts the filename to a platform specific filepath.
// On Android files can not be created in arbitrary directories.
static std::string GetSignalFilePath(const char* filename);
+
+ protected:
+ base::FilePath test_helper_path_;
};
std::string ProcessUtilTest::GetSignalFilePath(const char* filename) {
-#if !defined(OS_ANDROID)
- return filename;
-#else
+#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
FilePath tmp_dir;
- PathService::Get(DIR_CACHE, &tmp_dir);
+ PathService::Get(DIR_TEMP, &tmp_dir);
tmp_dir = tmp_dir.Append(filename);
return tmp_dir.value();
+#else
+ return filename;
#endif
}
@@ -238,17 +242,12 @@ MULTIPROCESS_TEST_MAIN(CheckTmpFileExists) {
}
TEST_F(ProcessUtilTest, SelectivelyClonedDir) {
- // Selective cloning only works if the test executable is deployed as a
- // package.
- if (GetPackageRoot().empty())
- return;
-
const std::string signal_file =
ProcessUtilTest::GetSignalFilePath(kSignalFileClone);
remove(signal_file.c_str());
LaunchOptions options;
- options.paths_to_map.push_back("/tmp");
+ options.paths_to_map.push_back(base::FilePath("/tmp"));
options.clone_flags = LP_CLONE_FDIO_STDIO;
Process process(SpawnChildWithOptions("CheckTmpFileExists", options));
@@ -265,18 +264,13 @@ TEST_F(ProcessUtilTest, SelectivelyClonedDir) {
// error code if it detects a directory other than "/tmp", so we can use that as
// a signal that it successfully detected another entry in the root namespace.
TEST_F(ProcessUtilTest, CloneAlternateDir) {
- // Selective cloning only works if the test executable is deployed as a
- // package.
- if (GetPackageRoot().empty())
- return;
-
const std::string signal_file =
ProcessUtilTest::GetSignalFilePath(kSignalFileClone);
remove(signal_file.c_str());
LaunchOptions options;
- options.paths_to_map.push_back("/tmp");
- options.paths_to_map.push_back("/data");
+ options.paths_to_map.push_back(base::FilePath("/tmp"));
+ options.paths_to_map.push_back(base::FilePath("/data"));
options.clone_flags = LP_CLONE_FDIO_STDIO;
Process process(SpawnChildWithOptions("CheckTmpFileExists", options));
@@ -289,7 +283,7 @@ TEST_F(ProcessUtilTest, CloneAlternateDir) {
EXPECT_EQ(1, exit_code);
}
-#endif
+#endif // defined(OS_FUCHSIA)
// On Android SpawnProcess() doesn't use LaunchProcess() and doesn't support
// LaunchOptions::current_directory.
@@ -357,7 +351,7 @@ const char kSignalFileCrash[] = "CrashingChildProcess.die";
MULTIPROCESS_TEST_MAIN(CrashingChildProcess) {
WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileCrash).c_str());
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
// Have to disable to signal handler for segv so we can get a crash
// instead of an abnormal termination through the crash dump handler.
::signal(SIGSEGV, SIG_DFL);
@@ -395,7 +389,7 @@ TEST_F(ProcessUtilTest, MAYBE_GetTerminationStatusCrash) {
#if defined(OS_WIN)
EXPECT_EQ(static_cast<int>(0xc0000005), exit_code);
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
int signaled = WIFSIGNALED(exit_code);
EXPECT_NE(0, signaled);
int signal = WTERMSIG(exit_code);
@@ -414,21 +408,21 @@ MULTIPROCESS_TEST_MAIN(KilledChildProcess) {
// Kill ourselves.
HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId());
::TerminateProcess(handle, kExpectedKilledExitCode);
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
// Send a SIGKILL to this process, just like the OOM killer would.
::kill(getpid(), SIGKILL);
#endif
return 1;
}
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
MULTIPROCESS_TEST_MAIN(TerminatedChildProcess) {
WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileTerm).c_str());
// Send a SIGTERM to this process.
::kill(getpid(), SIGTERM);
return 1;
}
-#endif // defined(OS_POSIX)
+#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
TEST_F(ProcessUtilTest, GetTerminationStatusSigKill) {
const std::string signal_file =
@@ -454,7 +448,7 @@ TEST_F(ProcessUtilTest, GetTerminationStatusSigKill) {
#if defined(OS_WIN)
EXPECT_EQ(kExpectedKilledExitCode, exit_code);
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
int signaled = WIFSIGNALED(exit_code);
EXPECT_NE(0, signaled);
int signal = WTERMSIG(exit_code);
@@ -463,7 +457,7 @@ TEST_F(ProcessUtilTest, GetTerminationStatusSigKill) {
remove(signal_file.c_str());
}
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
TEST_F(ProcessUtilTest, GetTerminationStatusSigTerm) {
const std::string signal_file =
ProcessUtilTest::GetSignalFilePath(kSignalFileTerm);
@@ -488,7 +482,7 @@ TEST_F(ProcessUtilTest, GetTerminationStatusSigTerm) {
EXPECT_EQ(SIGTERM, signal);
remove(signal_file.c_str());
}
-#endif // defined(OS_POSIX)
+#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
TEST_F(ProcessUtilTest, EnsureTerminationUndying) {
test::ScopedTaskEnvironment task_environment;
@@ -533,36 +527,6 @@ MULTIPROCESS_TEST_MAIN(process_util_test_die_immediately) {
#if defined(OS_WIN)
// TODO(estade): if possible, port this test.
-TEST_F(ProcessUtilTest, GetAppOutput) {
- // Let's create a decently long message.
- std::string message;
- for (int i = 0; i < 1025; i++) { // 1025 so it does not end on a kilo-byte
- // boundary.
- message += "Hello!";
- }
- // cmd.exe's echo always adds a \r\n to its output.
- std::string expected(message);
- expected += "\r\n";
-
- FilePath cmd(L"cmd.exe");
- CommandLine cmd_line(cmd);
- cmd_line.AppendArg("/c");
- cmd_line.AppendArg("echo " + message + "");
- std::string output;
- ASSERT_TRUE(GetAppOutput(cmd_line, &output));
- EXPECT_EQ(expected, output);
-
- // Let's make sure stderr is ignored.
- CommandLine other_cmd_line(cmd);
- other_cmd_line.AppendArg("/c");
- // http://msdn.microsoft.com/library/cc772622.aspx
- cmd_line.AppendArg("echo " + message + " >&2");
- output.clear();
- ASSERT_TRUE(GetAppOutput(other_cmd_line, &output));
- EXPECT_EQ("", output);
-}
-
-// TODO(estade): if possible, port this test.
TEST_F(ProcessUtilTest, LaunchAsUser) {
UserTokenHandle token;
ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token));
@@ -615,7 +579,55 @@ TEST_F(ProcessUtilTest, InheritSpecifiedHandles) {
}
#endif // defined(OS_WIN)
-#if defined(OS_POSIX)
+TEST_F(ProcessUtilTest, GetAppOutput) {
+ base::CommandLine command(test_helper_path_);
+ command.AppendArg("hello");
+ command.AppendArg("there");
+ command.AppendArg("good");
+ command.AppendArg("people");
+ std::string output;
+ EXPECT_TRUE(GetAppOutput(command, &output));
+ EXPECT_EQ("hello there good people", output);
+ output.clear();
+
+ const char* kEchoMessage = "blah";
+ command = base::CommandLine(test_helper_path_);
+ command.AppendArg("-x");
+ command.AppendArg("28");
+ command.AppendArg(kEchoMessage);
+ EXPECT_FALSE(GetAppOutput(command, &output));
+ EXPECT_EQ(kEchoMessage, output);
+}
+
+TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) {
+ const char* kEchoMessage1 = "doge";
+ int exit_code = -1;
+ base::CommandLine command(test_helper_path_);
+ command.AppendArg(kEchoMessage1);
+ std::string output;
+ EXPECT_TRUE(GetAppOutputWithExitCode(command, &output, &exit_code));
+ EXPECT_EQ(kEchoMessage1, output);
+ EXPECT_EQ(0, exit_code);
+ output.clear();
+
+ const char* kEchoMessage2 = "pupper";
+ const int kExpectedExitCode = 42;
+ command = base::CommandLine(test_helper_path_);
+ command.AppendArg("-x");
+ command.AppendArg(base::IntToString(kExpectedExitCode));
+ command.AppendArg(kEchoMessage2);
+#if defined(OS_WIN)
+ // On Windows, anything that quits with a nonzero status code is handled as a
+ // "crash", so just ignore GetAppOutputWithExitCode's return value.
+ GetAppOutputWithExitCode(command, &output, &exit_code);
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+ EXPECT_TRUE(GetAppOutputWithExitCode(command, &output, &exit_code));
+#endif
+ EXPECT_EQ(kEchoMessage2, output);
+ EXPECT_EQ(kExpectedExitCode, exit_code);
+}
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
namespace {
@@ -638,7 +650,7 @@ int GetMaxFilesOpenInProcess() {
}
return rlim.rlim_cur;
-#endif // !defined(OS_FUCHSIA)
+#endif // defined(OS_FUCHSIA)
}
const int kChildPipe = 20; // FD # for write end of pipe in child process.
@@ -863,9 +875,8 @@ TEST_F(ProcessUtilTest, FDRemappingIncludesStdio) {
EXPECT_EQ(0, exit_code);
}
-// TODO(https://crbug.com/793412): Disable on Debug/component builds due to
-// process launch taking too long and triggering timeouts.
-#if defined(OS_FUCHSIA) && defined(NDEBUG)
+#if defined(OS_FUCHSIA)
+
const uint16_t kStartupHandleId = 43;
MULTIPROCESS_TEST_MAIN(ProcessUtilsVerifyHandle) {
zx_handle_t handle =
@@ -920,7 +931,8 @@ TEST_F(ProcessUtilTest, LaunchWithHandleTransfer) {
&exit_code));
EXPECT_EQ(0, exit_code);
}
-#endif // defined(OS_FUCHSIA) && defined(NDEBUG)
+
+#endif // defined(OS_FUCHSIA)
namespace {
@@ -964,132 +976,54 @@ const char kLargeString[] =
} // namespace
TEST_F(ProcessUtilTest, LaunchProcess) {
- EnvironmentMap env_changes;
- std::vector<std::string> echo_base_test;
- echo_base_test.emplace_back(kShellPath);
- echo_base_test.emplace_back("-c");
- echo_base_test.emplace_back("echo $BASE_TEST");
-
- std::vector<std::string> print_env;
- print_env.emplace_back("/usr/bin/env");
const int no_clone_flags = 0;
const bool no_clear_environ = false;
-
const char kBaseTest[] = "BASE_TEST";
+ const std::vector<std::string> kPrintEnvCommand = {test_helper_path_.value(),
+ "-e", kBaseTest};
+ EnvironmentMap env_changes;
env_changes[kBaseTest] = "bar";
- EXPECT_EQ("bar\n",
- TestLaunchProcess(
- echo_base_test, env_changes, no_clear_environ, no_clone_flags));
+ EXPECT_EQ("bar", TestLaunchProcess(kPrintEnvCommand, env_changes,
+ no_clear_environ, no_clone_flags));
env_changes.clear();
EXPECT_EQ(0, setenv(kBaseTest, "testing", 1 /* override */));
- EXPECT_EQ("testing\n",
- TestLaunchProcess(
- echo_base_test, env_changes, no_clear_environ, no_clone_flags));
+ EXPECT_EQ("testing", TestLaunchProcess(kPrintEnvCommand, env_changes,
+ no_clear_environ, no_clone_flags));
env_changes[kBaseTest] = std::string();
- EXPECT_EQ("\n",
- TestLaunchProcess(
- echo_base_test, env_changes, no_clear_environ, no_clone_flags));
+ EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes,
+ no_clear_environ, no_clone_flags));
env_changes[kBaseTest] = "foo";
- EXPECT_EQ("foo\n",
- TestLaunchProcess(
- echo_base_test, env_changes, no_clear_environ, no_clone_flags));
+ EXPECT_EQ("foo", TestLaunchProcess(kPrintEnvCommand, 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(
- echo_base_test, env_changes, no_clear_environ, no_clone_flags));
+ EXPECT_EQ(std::string(kLargeString),
+ TestLaunchProcess(kPrintEnvCommand, env_changes, no_clear_environ,
+ no_clone_flags));
env_changes[kBaseTest] = "wibble";
- EXPECT_EQ("wibble\n",
- TestLaunchProcess(
- echo_base_test, env_changes, no_clear_environ, no_clone_flags));
+ EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes,
+ no_clear_environ, no_clone_flags));
#if defined(OS_LINUX)
// Test a non-trival value for clone_flags.
- EXPECT_EQ("wibble\n", TestLaunchProcess(echo_base_test, env_changes,
- no_clear_environ, CLONE_FS));
+ EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes,
+ no_clear_environ, CLONE_FS));
- EXPECT_EQ(
- "BASE_TEST=wibble\n",
- TestLaunchProcess(
- print_env, env_changes, true /* clear_environ */, no_clone_flags));
+ EXPECT_EQ("wibble",
+ TestLaunchProcess(kPrintEnvCommand, env_changes,
+ true /* clear_environ */, no_clone_flags));
env_changes.clear();
- EXPECT_EQ(
- "",
- TestLaunchProcess(
- print_env, env_changes, true /* clear_environ */, no_clone_flags));
+ EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes,
+ true /* clear_environ */, no_clone_flags));
#endif // defined(OS_LINUX)
}
-TEST_F(ProcessUtilTest, GetAppOutput) {
- std::string output;
-
-// There's no `true` or `false` on these platforms, so use exit 0/exit 1
-// instead.
-#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
- std::vector<std::string> argv;
-#if defined(OS_FUCHSIA)
- // There's no sh in PATH on Fuchsia by default, so provide a full path to sh.
- argv.emplace_back("/boot/bin/sh");
-#elif defined(OS_ANDROID)
- argv.emplace_back("sh"); // Instead of /bin/sh, force path search to find it.
-#else
-#error Port.
-#endif
- argv.emplace_back("-c");
-
- argv.emplace_back("exit 0");
- EXPECT_TRUE(GetAppOutput(CommandLine(argv), &output));
- EXPECT_STREQ("", output.c_str());
-
- argv[2] = "exit 1";
- EXPECT_FALSE(GetAppOutput(CommandLine(argv), &output));
- EXPECT_STREQ("", output.c_str());
-
- argv[2] = "echo foobar42";
- EXPECT_TRUE(GetAppOutput(CommandLine(argv), &output));
- EXPECT_STREQ("foobar42\n", output.c_str());
-#else
- EXPECT_TRUE(GetAppOutput(CommandLine(FilePath("true")), &output));
- EXPECT_STREQ("", output.c_str());
-
- EXPECT_FALSE(GetAppOutput(CommandLine(FilePath("false")), &output));
-
- std::vector<std::string> argv;
- argv.emplace_back("/bin/echo");
- argv.emplace_back("-n");
- argv.emplace_back("foobar42");
- EXPECT_TRUE(GetAppOutput(CommandLine(argv), &output));
- EXPECT_STREQ("foobar42", output.c_str());
-#endif // defined(OS_ANDROID)
-}
-
-TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) {
- // Test getting output from a successful application.
- std::vector<std::string> argv;
- std::string output;
- int exit_code;
- argv.emplace_back(kShellPath); // argv[0]
- argv.emplace_back("-c"); // argv[1]
- argv.emplace_back("echo foo"); // argv[2];
- EXPECT_TRUE(GetAppOutputWithExitCode(CommandLine(argv), &output, &exit_code));
- EXPECT_STREQ("foo\n", output.c_str());
- EXPECT_EQ(exit_code, kSuccess);
-
- // Test getting output from an application which fails with a specific exit
- // code.
- output.clear();
- argv[2] = "echo foo; exit 2";
- EXPECT_TRUE(GetAppOutputWithExitCode(CommandLine(argv), &output, &exit_code));
- EXPECT_STREQ("foo\n", output.c_str());
- EXPECT_EQ(exit_code, 2);
-}
-
// There's no such thing as a parent process id on Fuchsia.
#if !defined(OS_FUCHSIA)
TEST_F(ProcessUtilTest, GetParentProcessId) {
@@ -1138,7 +1072,7 @@ TEST_F(ProcessUtilTest, PreExecHook) {
}
#endif // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
-#endif // defined(OS_POSIX)
+#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
#if defined(OS_LINUX)
MULTIPROCESS_TEST_MAIN(CheckPidProcess) {