summaryrefslogtreecommitdiffstats
path: root/chromium/base/process
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-20 15:06:40 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-22 11:48:58 +0000
commitdaa093eea7c773db06799a13bd7e4e2e2a9f8f14 (patch)
tree96cc5e7b9194c1b29eab927730bfa419e7111c25 /chromium/base/process
parentbe59a35641616a4cf23c4a13fa0632624b021c1b (diff)
BASELINE: Update Chromium to 63.0.3239.58
Change-Id: Ia93b322a00ba4dd4004f3bcf1254063ba90e1605 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/base/process')
-rw-r--r--chromium/base/process/kill_fuchsia.cc24
-rw-r--r--chromium/base/process/launch.h18
-rw-r--r--chromium/base/process/launch_fuchsia.cc54
-rw-r--r--chromium/base/process/launch_mac.cc2
-rw-r--r--chromium/base/process/process.h19
-rw-r--r--chromium/base/process/process_fuchsia.cc92
-rw-r--r--chromium/base/process/process_handle.h12
-rw-r--r--chromium/base/process/process_handle_fuchsia.cc22
-rw-r--r--chromium/base/process/process_handle_linux.cc1
-rw-r--r--chromium/base/process/process_handle_win.cc2
-rw-r--r--chromium/base/process/process_mac.cc27
-rw-r--r--chromium/base/process/process_metrics.cc79
-rw-r--r--chromium/base/process/process_metrics.h56
-rw-r--r--chromium/base/process/process_metrics_freebsd.cc4
-rw-r--r--chromium/base/process/process_metrics_fuchsia.cc2
-rw-r--r--chromium/base/process/process_metrics_ios.cc2
-rw-r--r--chromium/base/process/process_metrics_linux.cc4
-rw-r--r--chromium/base/process/process_metrics_mac.cc48
-rw-r--r--chromium/base/process/process_metrics_openbsd.cc4
-rw-r--r--chromium/base/process/process_metrics_unittest.cc16
-rw-r--r--chromium/base/process/process_metrics_win.cc16
-rw-r--r--chromium/base/process/process_posix.cc21
-rw-r--r--chromium/base/process/process_unittest.cc28
-rw-r--r--chromium/base/process/process_util_unittest.cc50
24 files changed, 347 insertions, 256 deletions
diff --git a/chromium/base/process/kill_fuchsia.cc b/chromium/base/process/kill_fuchsia.cc
index d7bde1f4224..f4fdaae10b1 100644
--- a/chromium/base/process/kill_fuchsia.cc
+++ b/chromium/base/process/kill_fuchsia.cc
@@ -4,7 +4,7 @@
#include "base/process/kill.h"
-#include <magenta/syscalls.h>
+#include <zircon/syscalls.h>
#include "base/process/process_iterator.h"
#include "base/task_scheduler/post_task.h"
@@ -14,20 +14,20 @@ namespace base {
bool KillProcessGroup(ProcessHandle process_group_id) {
// |process_group_id| is really a job on Fuchsia.
- mx_status_t status = mx_task_kill(process_group_id);
- DLOG_IF(ERROR, status != MX_OK)
+ zx_status_t status = zx_task_kill(process_group_id);
+ DLOG_IF(ERROR, status != ZX_OK)
<< "unable to terminate job " << process_group_id;
- return status == MX_OK;
+ return status == ZX_OK;
}
TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
DCHECK(exit_code);
- mx_info_process_t process_info;
- mx_status_t status =
- mx_object_get_info(handle, MX_INFO_PROCESS, &process_info,
+ zx_info_process_t process_info;
+ zx_status_t status =
+ zx_object_get_info(handle, ZX_INFO_PROCESS, &process_info,
sizeof(process_info), nullptr, nullptr);
- if (status != MX_OK) {
+ if (status != ZX_OK) {
DLOG(ERROR) << "unable to get termination status for " << handle;
*exit_code = 0;
return TERMINATION_STATUS_NORMAL_TERMINATION;
@@ -55,10 +55,10 @@ void EnsureProcessTerminated(Process process) {
// Wait for up to two seconds for the process to terminate, and then kill it
// forcefully if it hasn't already exited.
- mx_signals_t signals;
- if (mx_object_wait_one(process.Handle(), MX_TASK_TERMINATED,
- mx_deadline_after(MX_SEC(2)), &signals) == MX_OK) {
- DCHECK(signals & MX_TASK_TERMINATED);
+ zx_signals_t signals;
+ if (zx_object_wait_one(process.Handle(), ZX_TASK_TERMINATED,
+ zx_deadline_after(ZX_SEC(2)), &signals) == ZX_OK) {
+ DCHECK(signals & ZX_TASK_TERMINATED);
// If already signaled, then the process is terminated.
return;
}
diff --git a/chromium/base/process/launch.h b/chromium/base/process/launch.h
index 9e7636da3e6..0c425a7a95c 100644
--- a/chromium/base/process/launch.h
+++ b/chromium/base/process/launch.h
@@ -28,7 +28,8 @@
#endif
#if defined(OS_FUCHSIA)
-#include <magenta/types.h>
+#include <launchpad/launchpad.h>
+#include <zircon/types.h>
#endif
namespace base {
@@ -42,7 +43,7 @@ typedef std::vector<HANDLE> HandlesToInheritVector;
#if defined(OS_FUCHSIA)
struct HandleToTransfer {
uint32_t id;
- mx_handle_t handle;
+ zx_handle_t handle;
};
typedef std::vector<HandleToTransfer> HandlesToTransferVector;
#endif
@@ -191,13 +192,22 @@ struct BASE_EXPORT LaunchOptions {
#if defined(OS_FUCHSIA)
// If valid, launches the application in that job object.
- mx_handle_t job_handle = MX_HANDLE_INVALID;
+ zx_handle_t job_handle = ZX_HANDLE_INVALID;
// Specifies additional handles to transfer (not duplicate) to the child
// process. The handles remain valid in this process if launch fails.
// Each entry is an <id,handle> pair, with an |id| created using the PA_HND()
- // macro. The child retrieves the handle |mx_get_startup_handle(id)|.
+ // macro. The child retrieves the handle |zx_get_startup_handle(id)|.
HandlesToTransferVector handles_to_transfer;
+
+ // If set, specifies which capabilities should be granted (cloned) to the
+ // child process.
+ // A zero value indicates that the child process will receive
+ // no capabilities.
+ // By default the child will inherit the same capabilities, job, and CWD
+ // from the parent process.
+ uint32_t clone_flags = LP_CLONE_FDIO_NAMESPACE | LP_CLONE_DEFAULT_JOB |
+ LP_CLONE_FDIO_CWD | LP_CLONE_FDIO_STDIO;
#endif // defined(OS_FUCHSIA)
#if defined(OS_POSIX)
diff --git a/chromium/base/process/launch_fuchsia.cc b/chromium/base/process/launch_fuchsia.cc
index 3f370880b27..16ac513b570 100644
--- a/chromium/base/process/launch_fuchsia.cc
+++ b/chromium/base/process/launch_fuchsia.cc
@@ -5,9 +5,10 @@
#include "base/process/launch.h"
#include <launchpad/launchpad.h>
-#include <magenta/process.h>
-#include <magenta/processargs.h>
+#include <stdint.h>
#include <unistd.h>
+#include <zircon/process.h>
+#include <zircon/processargs.h>
#include "base/command_line.h"
#include "base/fuchsia/default_job.h"
@@ -61,6 +62,8 @@ Process LaunchProcess(const CommandLine& cmdline,
return LaunchProcess(cmdline.argv(), options);
}
+// TODO(768416): Investigate whether we can make LaunchProcess() create
+// unprivileged processes by default (no implicit capabilities are granted).
Process LaunchProcess(const std::vector<std::string>& argv,
const LaunchOptions& options) {
std::vector<const char*> argv_cstr;
@@ -74,15 +77,15 @@ Process LaunchProcess(const std::vector<std::string>& argv,
// status is tracked in the launchpad_t object, and launchpad_go() reports on
// the final status, and cleans up |lp| (assuming it was even created).
launchpad_t* lp = nullptr;
- mx_handle_t job = options.job_handle != MX_HANDLE_INVALID ? options.job_handle
+ zx_handle_t job = options.job_handle != ZX_HANDLE_INVALID ? options.job_handle
: GetDefaultJob();
- DCHECK_NE(MX_HANDLE_INVALID, job);
+ DCHECK_NE(ZX_HANDLE_INVALID, job);
launchpad_create(job, argv_cstr[0], &lp);
launchpad_load_from_file(lp, argv_cstr[0]);
launchpad_set_args(lp, argv.size(), argv_cstr.data());
- uint32_t to_clone = LP_CLONE_MXIO_NAMESPACE | LP_CLONE_DEFAULT_JOB;
+ uint32_t to_clone = options.clone_flags;
std::unique_ptr<char* []> new_environ;
char* const empty_environ = nullptr;
@@ -93,20 +96,21 @@ Process LaunchProcess(const std::vector<std::string>& argv,
EnvironmentMap environ_modifications = options.environ;
if (!options.current_directory.empty()) {
environ_modifications["PWD"] = options.current_directory.value();
- } else {
- to_clone |= LP_CLONE_MXIO_CWD;
+
+ // Don't clone the parent's CWD if we are overriding the child's PWD.
+ to_clone = to_clone & ~LP_CLONE_FDIO_CWD;
}
if (to_clone & LP_CLONE_DEFAULT_JOB) {
// Override Fuchsia's built in default job cloning behavior with our own
- // logic which uses |job| instead of mx_job_default().
+ // logic which uses |job| instead of zx_job_default().
// This logic is based on the launchpad implementation.
- mx_handle_t job_duplicate = MX_HANDLE_INVALID;
- mx_status_t status =
- mx_handle_duplicate(job, MX_RIGHT_SAME_RIGHTS, &job_duplicate);
- if (status != MX_OK) {
- LOG(ERROR) << "mx_handle_duplicate(job): "
- << mx_status_get_string(status);
+ zx_handle_t job_duplicate = ZX_HANDLE_INVALID;
+ zx_status_t status =
+ zx_handle_duplicate(job, ZX_RIGHT_SAME_RIGHTS, &job_duplicate);
+ if (status != ZX_OK) {
+ LOG(ERROR) << "zx_handle_duplicate(job): "
+ << zx_status_get_string(status);
return Process();
}
launchpad_add_handle(lp, job_duplicate, PA_HND(PA_JOB_DEFAULT, 0));
@@ -127,26 +131,30 @@ Process LaunchProcess(const std::vector<std::string>& argv,
bool stdio_already_mapped[3] = {false};
for (const auto& src_target : options.fds_to_remap) {
if (static_cast<size_t>(src_target.second) <
- arraysize(stdio_already_mapped))
+ arraysize(stdio_already_mapped)) {
stdio_already_mapped[src_target.second] = true;
+ }
launchpad_clone_fd(lp, src_target.first, src_target.second);
}
- for (size_t stdio_fd = 0; stdio_fd < arraysize(stdio_already_mapped);
- ++stdio_fd) {
- if (!stdio_already_mapped[stdio_fd])
- launchpad_clone_fd(lp, stdio_fd, stdio_fd);
+ if (to_clone & LP_CLONE_FDIO_STDIO) {
+ for (size_t stdio_fd = 0; stdio_fd < arraysize(stdio_already_mapped);
+ ++stdio_fd) {
+ if (!stdio_already_mapped[stdio_fd])
+ launchpad_clone_fd(lp, stdio_fd, stdio_fd);
+ }
+ to_clone &= ~LP_CLONE_FDIO_STDIO;
}
for (const auto& id_and_handle : options.handles_to_transfer) {
launchpad_add_handle(lp, id_and_handle.handle, id_and_handle.id);
}
- mx_handle_t proc;
+ zx_handle_t proc;
const char* errmsg;
- mx_status_t status = launchpad_go(lp, &proc, &errmsg);
- if (status != MX_OK) {
+ zx_status_t status = launchpad_go(lp, &proc, &errmsg);
+ if (status != ZX_OK) {
LOG(ERROR) << "launchpad_go failed: " << errmsg
- << ", status=" << mx_status_get_string(status);
+ << ", status=" << zx_status_get_string(status);
return Process();
}
diff --git a/chromium/base/process/launch_mac.cc b/chromium/base/process/launch_mac.cc
index b8ff49ce1ac..dfa9257a51e 100644
--- a/chromium/base/process/launch_mac.cc
+++ b/chromium/base/process/launch_mac.cc
@@ -76,7 +76,7 @@ class PosixSpawnFileActions {
void RestoreDefaultExceptionHandler() {
// This function is tailored to remove the Breakpad exception handler.
// exception_mask matches s_exception_mask in
- // breakpad/src/client/mac/handler/exception_handler.cc
+ // third_party/breakpad/breakpad/src/client/mac/handler/exception_handler.cc
const exception_mask_t exception_mask = EXC_MASK_BAD_ACCESS |
EXC_MASK_BAD_INSTRUCTION |
EXC_MASK_ARITHMETIC |
diff --git a/chromium/base/process/process.h b/chromium/base/process/process.h
index a4d77dfad85..481d92ddc17 100644
--- a/chromium/base/process/process.h
+++ b/chromium/base/process/process.h
@@ -16,7 +16,7 @@
#endif
#if defined(OS_FUCHSIA)
-#include "base/fuchsia/scoped_mx_handle.h"
+#include "base/fuchsia/scoped_zx_handle.h"
#endif
#if defined(OS_MACOSX)
@@ -45,6 +45,8 @@ extern const Feature kMacAllowBackgroundingProcesses;
// end up pointing to the wrong process.
class BASE_EXPORT Process {
public:
+ // On Windows, this takes ownership of |handle|. On POSIX, this does not take
+ // ownership of |handle|.
explicit Process(ProcessHandle handle = kNullProcessHandle);
Process(Process&& other);
@@ -102,6 +104,16 @@ class BASE_EXPORT Process {
// Close the process handle. This will not terminate the process.
void Close();
+ // Returns true if this process is still running. This is only safe on Windows
+ // (and maybe Fuchsia?), because the ProcessHandle will keep the zombie
+ // process information available until itself has been released. But on Posix,
+ // the OS may reuse the ProcessId.
+#if defined(OS_WIN)
+ bool IsRunning() const {
+ return !WaitForExitWithTimeout(base::TimeDelta(), nullptr);
+ }
+#endif
+
// Terminates the process with extreme prejudice. The given |exit_code| will
// be the exit code of the process. If |wait| is true, this method will wait
// for up to one minute for the process to actually terminate.
@@ -143,9 +155,6 @@ class BASE_EXPORT Process {
// Returns true if the priority was changed, false otherwise. If
// |port_provider| is null, this is a no-op and it returns false.
bool SetProcessBackgrounded(PortProvider* port_provider, bool value);
-
- // Returns |true| if helper processes should participate in AppNap.
- static bool IsAppNapEnabled();
#else
// A process is backgrounded when it's priority is lower than normal.
// Return true if this process is backgrounded, false otherwise.
@@ -172,7 +181,7 @@ class BASE_EXPORT Process {
#if defined(OS_WIN)
win::ScopedHandle process_;
#elif defined(OS_FUCHSIA)
- ScopedMxHandle process_;
+ ScopedZxHandle process_;
#else
ProcessHandle process_;
#endif
diff --git a/chromium/base/process/process_fuchsia.cc b/chromium/base/process/process_fuchsia.cc
index 43efbf08805..57da2ae4368 100644
--- a/chromium/base/process/process_fuchsia.cc
+++ b/chromium/base/process/process_fuchsia.cc
@@ -4,8 +4,8 @@
#include "base/process/process.h"
-#include <magenta/process.h>
-#include <magenta/syscalls.h>
+#include <zircon/process.h>
+#include <zircon/syscalls.h>
#include "base/debug/activity_tracker.h"
#include "base/fuchsia/default_job.h"
@@ -15,7 +15,7 @@ namespace base {
Process::Process(ProcessHandle handle)
: process_(handle), is_current_process_(false) {
- CHECK_NE(handle, mx_process_self());
+ CHECK_NE(handle, zx_process_self());
}
Process::~Process() {
@@ -48,12 +48,12 @@ Process Process::Open(ProcessId pid) {
return Current();
// While a process with object id |pid| might exist, the job returned by
- // mx_job_default() might not contain it, so this call can fail.
- ScopedMxHandle handle;
- mx_status_t status = mx_object_get_child(
- GetDefaultJob(), pid, MX_RIGHT_SAME_RIGHTS, handle.receive());
- if (status != MX_OK) {
- DLOG(ERROR) << "mx_object_get_child failed: " << status;
+ // zx_job_default() might not contain it, so this call can fail.
+ ScopedZxHandle handle;
+ zx_status_t status = zx_object_get_child(
+ GetDefaultJob(), pid, ZX_RIGHT_SAME_RIGHTS, handle.receive());
+ if (status != ZX_OK) {
+ DLOG(ERROR) << "zx_object_get_child failed: " << status;
return Process();
}
return Process(handle.release());
@@ -68,10 +68,10 @@ Process Process::OpenWithExtraPrivileges(ProcessId pid) {
// static
Process Process::DeprecatedGetProcessFromHandle(ProcessHandle handle) {
DCHECK_NE(handle, GetCurrentProcessHandle());
- ScopedMxHandle out;
- if (mx_handle_duplicate(handle, MX_RIGHT_SAME_RIGHTS, out.receive()) !=
- MX_OK) {
- DLOG(ERROR) << "mx_handle_duplicate failed: " << handle;
+ ScopedZxHandle out;
+ if (zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS, out.receive()) !=
+ ZX_OK) {
+ DLOG(ERROR) << "zx_handle_duplicate failed: " << handle;
return Process();
}
@@ -93,7 +93,7 @@ bool Process::IsValid() const {
}
ProcessHandle Process::Handle() const {
- return is_current_process_ ? mx_process_self() : process_.get();
+ return is_current_process_ ? zx_process_self() : process_.get();
}
Process Process::Duplicate() const {
@@ -103,10 +103,10 @@ Process Process::Duplicate() const {
if (!IsValid())
return Process();
- ScopedMxHandle out;
- if (mx_handle_duplicate(process_.get(), MX_RIGHT_SAME_RIGHTS,
- out.receive()) != MX_OK) {
- DLOG(ERROR) << "mx_handle_duplicate failed: " << process_.get();
+ ScopedZxHandle out;
+ if (zx_handle_duplicate(process_.get(), ZX_RIGHT_SAME_RIGHTS,
+ out.receive()) != ZX_OK) {
+ DLOG(ERROR) << "zx_handle_duplicate failed: " << process_.get();
return Process();
}
@@ -129,19 +129,19 @@ void Process::Close() {
bool Process::Terminate(int exit_code, bool wait) const {
// exit_code isn't supportable. https://crbug.com/753490.
- mx_status_t status = mx_task_kill(Handle());
+ zx_status_t status = zx_task_kill(Handle());
// TODO(scottmg): Put these LOG/CHECK back to DLOG/DCHECK after
// https://crbug.com/750756 is diagnosed.
- if (status == MX_OK && wait) {
- mx_signals_t signals;
- status = mx_object_wait_one(Handle(), MX_TASK_TERMINATED,
- mx_deadline_after(MX_SEC(60)), &signals);
- if (status != MX_OK) {
+ if (status == ZX_OK && wait) {
+ zx_signals_t signals;
+ status = zx_object_wait_one(Handle(), ZX_TASK_TERMINATED,
+ zx_deadline_after(ZX_SEC(60)), &signals);
+ if (status != ZX_OK) {
LOG(ERROR) << "Error waiting for process exit: " << status;
} else {
- CHECK(signals & MX_TASK_TERMINATED);
+ CHECK(signals & ZX_TASK_TERMINATED);
}
- } else if (status != MX_OK) {
+ } else if (status != ZX_OK) {
LOG(ERROR) << "Unable to terminate process: " << status;
}
@@ -153,49 +153,53 @@ bool Process::WaitForExit(int* exit_code) const {
}
bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) const {
- DCHECK(!is_current_process_);
+ if (is_current_process_)
+ return false;
// Record the event that this thread is blocking upon (for hang diagnosis).
base::debug::ScopedProcessWaitActivity process_activity(this);
- mx_time_t deadline = timeout == TimeDelta::Max()
- ? MX_TIME_INFINITE
- : (TimeTicks::Now() + timeout).ToMXTime();
+ zx_time_t deadline = timeout == TimeDelta::Max()
+ ? ZX_TIME_INFINITE
+ : (TimeTicks::Now() + timeout).ToZxTime();
// TODO(scottmg): https://crbug.com/755282
const bool kOnBot = getenv("CHROME_HEADLESS") != nullptr;
if (kOnBot) {
LOG(ERROR) << base::StringPrintf(
"going to wait for process %x (deadline=%zu, now=%zu)", process_.get(),
- deadline, TimeTicks::Now().ToMXTime());
+ deadline, TimeTicks::Now().ToZxTime());
}
- mx_signals_t signals_observed = 0;
- mx_status_t status = mx_object_wait_one(process_.get(), MX_TASK_TERMINATED,
+ zx_signals_t signals_observed = 0;
+ zx_status_t status = zx_object_wait_one(process_.get(), ZX_TASK_TERMINATED,
deadline, &signals_observed);
// TODO(scottmg): Make these LOGs into DLOGs after https://crbug.com/750756 is
// fixed.
- *exit_code = -1;
- if (status != MX_OK && status != MX_ERR_TIMED_OUT) {
- LOG(ERROR) << "mx_object_wait_one failed, status=" << status;
+ if (status != ZX_OK && status != ZX_ERR_TIMED_OUT) {
+ LOG(ERROR) << "zx_object_wait_one failed, status=" << status;
return false;
}
- if (status == MX_ERR_TIMED_OUT) {
- mx_time_t now = TimeTicks::Now().ToMXTime();
- LOG(ERROR) << "mx_object_wait_one timed out, signals=" << signals_observed
+ if (status == ZX_ERR_TIMED_OUT) {
+ zx_time_t now = TimeTicks::Now().ToZxTime();
+ LOG(ERROR) << "zx_object_wait_one timed out, signals=" << signals_observed
<< ", deadline=" << deadline << ", now=" << now
<< ", delta=" << (now - deadline);
return false;
}
- mx_info_process_t proc_info;
- status = mx_object_get_info(process_.get(), MX_INFO_PROCESS, &proc_info,
+ zx_info_process_t proc_info;
+ status = zx_object_get_info(process_.get(), ZX_INFO_PROCESS, &proc_info,
sizeof(proc_info), nullptr, nullptr);
- if (status != MX_OK) {
- LOG(ERROR) << "mx_object_get_info failed, status=" << status;
+ if (status != ZX_OK) {
+ LOG(ERROR) << "zx_object_get_info failed, status=" << status;
+ if (exit_code)
+ *exit_code = -1;
return false;
}
- *exit_code = proc_info.return_code;
+ if (exit_code)
+ *exit_code = proc_info.return_code;
+
return true;
}
diff --git a/chromium/base/process/process_handle.h b/chromium/base/process/process_handle.h
index 48b8aa48b09..ae54b72d999 100644
--- a/chromium/base/process/process_handle.h
+++ b/chromium/base/process/process_handle.h
@@ -17,7 +17,7 @@
#endif
#if defined(OS_FUCHSIA)
-#include <magenta/types.h>
+#include <zircon/types.h>
#endif
namespace base {
@@ -32,10 +32,10 @@ typedef HANDLE UserTokenHandle;
const ProcessHandle kNullProcessHandle = NULL;
const ProcessId kNullProcessId = 0;
#elif defined(OS_FUCHSIA)
-typedef mx_handle_t ProcessHandle;
-typedef mx_koid_t ProcessId;
-const ProcessHandle kNullProcessHandle = MX_HANDLE_INVALID;
-const ProcessId kNullProcessId = MX_KOID_INVALID;
+typedef zx_handle_t ProcessHandle;
+typedef zx_koid_t ProcessId;
+const ProcessHandle kNullProcessHandle = ZX_HANDLE_INVALID;
+const ProcessId kNullProcessId = ZX_KOID_INVALID;
#elif defined(OS_POSIX)
// On POSIX, our ProcessHandle will just be the PID.
typedef pid_t ProcessHandle;
@@ -88,6 +88,8 @@ BASE_EXPORT ProcessId GetProcId(ProcessHandle process);
#if !defined(OS_FUCHSIA)
// Returns the ID for the parent of the given process. Not available on Fuchsia.
+// Returning a negative value indicates an error, such as if the |process| does
+// not exist. Returns 0 when |process| has no parent process.
BASE_EXPORT ProcessId GetParentProcessId(ProcessHandle process);
#endif // !defined(OS_FUCHSIA)
diff --git a/chromium/base/process/process_handle_fuchsia.cc b/chromium/base/process/process_handle_fuchsia.cc
index 2d6e1668b1c..c9d2a8e4d44 100644
--- a/chromium/base/process/process_handle_fuchsia.cc
+++ b/chromium/base/process/process_handle_fuchsia.cc
@@ -4,9 +4,9 @@
#include "base/process/process_handle.h"
-#include <magenta/process.h>
-#include <magenta/status.h>
-#include <magenta/syscalls.h>
+#include <zircon/process.h>
+#include <zircon/status.h>
+#include <zircon/syscalls.h>
#include "base/logging.h"
@@ -17,19 +17,19 @@ ProcessId GetCurrentProcId() {
}
ProcessHandle GetCurrentProcessHandle() {
- // Note that mx_process_self() returns a real handle, and ownership is not
+ // Note that zx_process_self() returns a real handle, and ownership is not
// transferred to the caller (i.e. this should never be closed).
- return mx_process_self();
+ return zx_process_self();
}
ProcessId GetProcId(ProcessHandle process) {
- mx_info_handle_basic_t basic;
- mx_status_t status = mx_object_get_info(process, MX_INFO_HANDLE_BASIC, &basic,
+ zx_info_handle_basic_t basic;
+ zx_status_t status = zx_object_get_info(process, ZX_INFO_HANDLE_BASIC, &basic,
sizeof(basic), nullptr, nullptr);
- if (status != MX_OK) {
- DLOG(ERROR) << "mx_object_get_info failed: "
- << mx_status_get_string(status);
- return MX_KOID_INVALID;
+ if (status != ZX_OK) {
+ DLOG(ERROR) << "zx_object_get_info failed: "
+ << zx_status_get_string(status);
+ return ZX_KOID_INVALID;
}
return basic.koid;
}
diff --git a/chromium/base/process/process_handle_linux.cc b/chromium/base/process/process_handle_linux.cc
index 3a0460725e0..f921b426a36 100644
--- a/chromium/base/process/process_handle_linux.cc
+++ b/chromium/base/process/process_handle_linux.cc
@@ -20,6 +20,7 @@ ProcessId GetParentProcessId(ProcessHandle process) {
#else
internal::ReadProcStatsAndGetFieldAsInt64(process, internal::VM_PPID);
#endif
+ // TODO(zijiehe): Returns 0 if |process| does not have a parent process.
if (pid)
return pid;
return -1;
diff --git a/chromium/base/process/process_handle_win.cc b/chromium/base/process/process_handle_win.cc
index b8136d1e8cc..67986cd21d9 100644
--- a/chromium/base/process/process_handle_win.cc
+++ b/chromium/base/process/process_handle_win.cc
@@ -38,6 +38,8 @@ ProcessId GetParentProcessId(ProcessHandle process) {
} while (Process32Next(snapshot.Get(), &process_entry));
}
+ // TODO(zijiehe): To match other platforms, -1 (UINT32_MAX) should be returned
+ // if |child_id| cannot be found in the |snapshot|.
return 0u;
}
diff --git a/chromium/base/process/process_mac.cc b/chromium/base/process/process_mac.cc
index bc045cd72aa..70bc4c20fd0 100644
--- a/chromium/base/process/process_mac.cc
+++ b/chromium/base/process/process_mac.cc
@@ -8,27 +8,15 @@
#include "base/feature_list.h"
#include "base/mac/mach_logging.h"
-#include "base/metrics/field_trial_params.h"
namespace base {
-namespace {
-const char kAppNapFeatureParamName[] = "app_nap";
-}
-
// Enables backgrounding hidden renderers on Mac.
const Feature kMacAllowBackgroundingProcesses{"MacAllowBackgroundingProcesses",
FEATURE_DISABLED_BY_DEFAULT};
-bool Process::IsAppNapEnabled() {
- return !base::GetFieldTrialParamValueByFeature(
- kMacAllowBackgroundingProcesses, kAppNapFeatureParamName)
- .empty();
-}
-
bool Process::CanBackgroundProcesses() {
- return FeatureList::IsEnabled(kMacAllowBackgroundingProcesses) &&
- !IsAppNapEnabled();
+ return FeatureList::IsEnabled(kMacAllowBackgroundingProcesses);
}
bool Process::IsProcessBackgrounded(PortProvider* port_provider) const {
@@ -83,19 +71,6 @@ bool Process::SetProcessBackgrounded(PortProvider* port_provider,
return false;
}
- // Latency QoS regulates timer throttling/accuracy. Select default tier
- // on foreground because precise timer firing isn't needed.
- struct task_qos_policy qos_policy = {
- background ? LATENCY_QOS_TIER_5 : LATENCY_QOS_TIER_UNSPECIFIED,
- background ? THROUGHPUT_QOS_TIER_5 : THROUGHPUT_QOS_TIER_UNSPECIFIED};
- result = task_policy_set(task_port, TASK_OVERRIDE_QOS_POLICY,
- reinterpret_cast<task_policy_t>(&qos_policy),
- TASK_QOS_POLICY_COUNT);
- if (result != KERN_SUCCESS) {
- MACH_LOG(ERROR, result) << "task_policy_set TASK_OVERRIDE_QOS_POLICY";
- return false;
- }
-
return true;
}
diff --git a/chromium/base/process/process_metrics.cc b/chromium/base/process/process_metrics.cc
index f24901c3d99..0d9140a99e8 100644
--- a/chromium/base/process/process_metrics.cc
+++ b/chromium/base/process/process_metrics.cc
@@ -10,6 +10,40 @@
#include "base/values.h"
#include "build/build_config.h"
+#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
+namespace {
+int CalculateEventsPerSecond(uint64_t event_count,
+ uint64_t* last_event_count,
+ base::TimeTicks* last_calculated) {
+ base::TimeTicks time = base::TimeTicks::Now();
+
+ if (*last_event_count == 0) {
+ // First call, just set the last values.
+ *last_calculated = time;
+ *last_event_count = event_count;
+ return 0;
+ }
+
+ int64_t events_delta = event_count - *last_event_count;
+ int64_t time_delta = (time - *last_calculated).InMicroseconds();
+ if (time_delta == 0) {
+ NOTREACHED();
+ return 0;
+ }
+
+ *last_calculated = time;
+ *last_event_count = event_count;
+
+ int64_t events_delta_for_ms =
+ events_delta * base::Time::kMicrosecondsPerSecond;
+ // Round the result up by adding 1/2 (the second term resolves to 1/2 without
+ // dropping down into floating point).
+ return (events_delta_for_ms + time_delta / 2) / time_delta;
+}
+
+} // namespace
+#endif // defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
+
namespace base {
SystemMemoryInfoKB::SystemMemoryInfoKB() = default;
@@ -59,46 +93,27 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateCurrentProcessMetrics() {
#endif // !defined(OS_MACOSX) || defined(OS_IOS)
}
-double ProcessMetrics::GetPlatformIndependentCPUUsage() {
-#if defined(OS_WIN)
- return GetCPUUsage() * processor_count_;
-#else
- return GetCPUUsage();
-#endif
-}
-
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
int ProcessMetrics::CalculateIdleWakeupsPerSecond(
uint64_t absolute_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_t wakeups_delta = absolute_idle_wakeups - last_absolute_idle_wakeups_;
- int64_t time_delta = (time - last_idle_wakeups_time_).InMicroseconds();
- if (time_delta == 0) {
- NOTREACHED();
- return 0;
- }
-
- last_idle_wakeups_time_ = time;
- last_absolute_idle_wakeups_ = absolute_idle_wakeups;
-
- int64_t wakeups_delta_for_ms = wakeups_delta * Time::kMicrosecondsPerSecond;
- // Round the result up by adding 1/2 (the second term resolves to 1/2 without
- // dropping down into floating point).
- return (wakeups_delta_for_ms + time_delta / 2) / time_delta;
+ return CalculateEventsPerSecond(absolute_idle_wakeups,
+ &last_absolute_idle_wakeups_,
+ &last_idle_wakeups_time_);
}
#else
int ProcessMetrics::GetIdleWakeupsPerSecond() {
NOTIMPLEMENTED(); // http://crbug.com/120488
return 0;
}
-#endif // defined(OS_MACOSX) || defined(OS_LINUX)
+#endif // defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
+
+#if defined(OS_MACOSX)
+int ProcessMetrics::CalculatePackageIdleWakeupsPerSecond(
+ uint64_t absolute_package_idle_wakeups) {
+ return CalculateEventsPerSecond(absolute_package_idle_wakeups,
+ &last_absolute_package_idle_wakeups_,
+ &last_package_idle_wakeups_time_);
+}
+#endif // defined(OS_MACOSX)
} // namespace base
diff --git a/chromium/base/process/process_metrics.h b/chromium/base/process/process_metrics.h
index 644b463242f..844cd73cb4a 100644
--- a/chromium/base/process/process_metrics.h
+++ b/chromium/base/process/process_metrics.h
@@ -203,22 +203,40 @@ class BASE_EXPORT ProcessMetrics {
size_t* locked_bytes) const;
#endif
- // Returns the CPU usage in percent since the last time this method or
- // GetPlatformIndependentCPUUsage() was called. The first time this method
- // is called it returns 0 and will return the actual CPU info on subsequent
- // calls. On Windows, the CPU usage value is for all CPUs. So if you have
- // 2 CPUs and your process is using all the cycles of 1 CPU and not the other
- // CPU, this method returns 50.
- double GetCPUUsage();
+ // Returns the percentage of time spent executing, across all threads of the
+ // process, in the interval since the last time the method was called. Since
+ // this considers the total execution time across all threads in a process,
+ // the result can easily exceed 100% in multi-thread processes running on
+ // multi-core systems. In general the result is therefore a value in the
+ // range 0% to SysInfo::NumberOfProcessors() * 100%.
+ //
+ // To obtain the percentage of total available CPU resources consumed by this
+ // process over the interval, the caller must divide by NumberOfProcessors().
+ //
+ // Since this API measures usage over an interval, it will return zero on the
+ // first call, and an actual value only on the second and subsequent calls.
+ double GetPlatformIndependentCPUUsage();
// 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.
- double GetPlatformIndependentCPUUsage();
+#if defined(OS_MACOSX)
+ // Returns the number of average "package idle exits" per second, which have
+ // a higher energy impact than a regular wakeup, since the last call.
+ //
+ // From the powermetrics man page:
+ // "With the exception of some Mac Pro systems, Mac and
+ // iOS systems are typically single package systems, wherein all CPUs are
+ // part of a single processor complex (typically a single IC die) with shared
+ // logic that can include (depending on system specifics) shared last level
+ // caches, an integrated memory controller etc. When all CPUs in the package
+ // are idle, the hardware can power-gate significant portions of the shared
+ // logic in addition to each individual processor's logic, as well as take
+ // measures such as placing DRAM in to self-refresh (also referred to as
+ // auto-refresh), place interconnects into lower-power states etc"
+ int GetPackageIdleWakeupsPerSecond();
+#endif
// Retrieves accounting information for all I/O operations performed by the
// process.
@@ -267,6 +285,12 @@ class BASE_EXPORT ProcessMetrics {
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
int CalculateIdleWakeupsPerSecond(uint64_t absolute_idle_wakeups);
#endif
+#if defined(OS_MACOSX)
+ // The subset of wakeups that cause a "package exit" can be tracked on macOS.
+ // See |GetPackageIdleWakeupsForSecond| comment for more info.
+ int CalculatePackageIdleWakeupsPerSecond(
+ uint64_t absolute_package_idle_wakeups);
+#endif
#if defined(OS_WIN)
win::ScopedHandle process_;
@@ -274,8 +298,6 @@ class BASE_EXPORT ProcessMetrics {
ProcessHandle process_;
#endif
- int processor_count_;
-
// Used to store the previous times and CPU usage counts so we can
// compute the CPU usage between calls.
TimeTicks last_cpu_time_;
@@ -287,6 +309,12 @@ class BASE_EXPORT ProcessMetrics {
uint64_t last_absolute_idle_wakeups_;
#endif
+#if defined(OS_MACOSX)
+ // And same thing for package idle exit wakeups.
+ TimeTicks last_package_idle_wakeups_time_;
+ uint64_t last_absolute_package_idle_wakeups_;
+#endif
+
#if !defined(OS_IOS)
#if defined(OS_MACOSX)
// Queries the port provider if it's set.
@@ -312,11 +340,11 @@ BASE_EXPORT size_t GetSystemCommitCharge();
// returned by GetPageSize().
BASE_EXPORT size_t GetPageSize();
-#if defined(OS_POSIX)
// 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.
BASE_EXPORT size_t GetMaxFds();
+#if defined(OS_POSIX)
// 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);
diff --git a/chromium/base/process/process_metrics_freebsd.cc b/chromium/base/process/process_metrics_freebsd.cc
index 4f5adf790f6..10d0868d198 100644
--- a/chromium/base/process/process_metrics_freebsd.cc
+++ b/chromium/base/process/process_metrics_freebsd.cc
@@ -11,13 +11,11 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/sys_info.h"
namespace base {
ProcessMetrics::ProcessMetrics(ProcessHandle process)
: process_(process),
- processor_count_(SysInfo::NumberOfProcessors()),
last_system_time_(0),
last_cpu_(0) {}
@@ -84,7 +82,7 @@ bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
return true;
}
-double ProcessMetrics::GetCPUUsage() {
+double ProcessMetrics::GetPlatformIndependentCPUUsage() {
struct kinfo_proc info;
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_ };
size_t length = sizeof(info);
diff --git a/chromium/base/process/process_metrics_fuchsia.cc b/chromium/base/process/process_metrics_fuchsia.cc
index 6fcdb5ce2d0..a5234c40a79 100644
--- a/chromium/base/process/process_metrics_fuchsia.cc
+++ b/chromium/base/process/process_metrics_fuchsia.cc
@@ -19,7 +19,7 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
return nullptr;
}
-double ProcessMetrics::GetCPUUsage() {
+double ProcessMetrics::GetPlatformIndependentCPUUsage() {
NOTIMPLEMENTED(); // TODO(fuchsia): https://crbug.com/706592.
return 0.0;
}
diff --git a/chromium/base/process/process_metrics_ios.cc b/chromium/base/process/process_metrics_ios.cc
index 2ed65ab37f9..31c812dee03 100644
--- a/chromium/base/process/process_metrics_ios.cc
+++ b/chromium/base/process/process_metrics_ios.cc
@@ -38,7 +38,7 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
return WrapUnique(new ProcessMetrics(process));
}
-double ProcessMetrics::GetCPUUsage() {
+double ProcessMetrics::GetPlatformIndependentCPUUsage() {
NOTIMPLEMENTED();
return 0;
}
diff --git a/chromium/base/process/process_metrics_linux.cc b/chromium/base/process/process_metrics_linux.cc
index d6b28bd48a0..6a32964d22d 100644
--- a/chromium/base/process/process_metrics_linux.cc
+++ b/chromium/base/process/process_metrics_linux.cc
@@ -24,7 +24,6 @@
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
-#include "base/sys_info.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
@@ -256,7 +255,7 @@ bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
return GetWorkingSetKBytesStatm(ws_usage);
}
-double ProcessMetrics::GetCPUUsage() {
+double ProcessMetrics::GetPlatformIndependentCPUUsage() {
TimeTicks time = TimeTicks::Now();
if (last_cpu_ == 0) {
@@ -405,7 +404,6 @@ ProcessMetrics::ProcessMetrics(ProcessHandle process)
last_absolute_idle_wakeups_(0),
#endif
last_cpu_(0) {
- processor_count_ = SysInfo::NumberOfProcessors();
}
#if defined(OS_CHROMEOS)
diff --git a/chromium/base/process/process_metrics_mac.cc b/chromium/base/process/process_metrics_mac.cc
index 710f096069b..98793ff2413 100644
--- a/chromium/base/process/process_metrics_mac.cc
+++ b/chromium/base/process/process_metrics_mac.cc
@@ -19,7 +19,6 @@
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/numerics/safe_math.h"
-#include "base/sys_info.h"
namespace base {
@@ -105,6 +104,18 @@ MachVMRegionResult ParseOutputFromMachVMRegion(kern_return_t kr) {
return MachVMRegionResult::Success;
}
+bool GetPowerInfo(mach_port_t task, task_power_info* power_info_data) {
+ if (task == MACH_PORT_NULL)
+ return false;
+
+ 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);
+ // Most likely cause for failure: |task| is a zombie.
+ return kr == KERN_SUCCESS;
+}
+
} // namespace
// Getting a mach task from a pid for another process requires permissions in
@@ -309,7 +320,7 @@ ProcessMetrics::TaskVMInfo ProcessMetrics::GetTaskVMInfo() const {
(r)->tv_usec = (a)->microseconds; \
} while (0)
-double ProcessMetrics::GetCPUUsage() {
+double ProcessMetrics::GetPlatformIndependentCPUUsage() {
mach_port_t task = TaskForPid(process_);
if (task == MACH_PORT_NULL)
return 0;
@@ -366,22 +377,11 @@ double ProcessMetrics::GetCPUUsage() {
return static_cast<double>(system_time_delta * 100.0) / time_delta;
}
-int ProcessMetrics::GetIdleWakeupsPerSecond() {
+int ProcessMetrics::GetPackageIdleWakeupsPerSecond() {
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;
- }
+
+ GetPowerInfo(task, &power_info_data);
// The task_power_info struct contains two wakeup counters:
// task_interrupt_wakeups and task_platform_idle_wakeups.
@@ -393,10 +393,19 @@ int ProcessMetrics::GetIdleWakeupsPerSecond() {
// in a greater power increase than the other interrupts which occur while the
// CPU is already working, and reducing them has a greater overall impact on
// power usage. See the powermetrics man page for more info.
- return CalculateIdleWakeupsPerSecond(
+ return CalculatePackageIdleWakeupsPerSecond(
power_info_data.task_platform_idle_wakeups);
}
+int ProcessMetrics::GetIdleWakeupsPerSecond() {
+ mach_port_t task = TaskForPid(process_);
+ task_power_info power_info_data;
+
+ GetPowerInfo(task, &power_info_data);
+
+ return CalculateIdleWakeupsPerSecond(power_info_data.task_interrupt_wakeups);
+}
+
bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
return false;
}
@@ -406,9 +415,8 @@ ProcessMetrics::ProcessMetrics(ProcessHandle process,
: process_(process),
last_system_time_(0),
last_absolute_idle_wakeups_(0),
- port_provider_(port_provider) {
- processor_count_ = SysInfo::NumberOfProcessors();
-}
+ last_absolute_package_idle_wakeups_(0),
+ port_provider_(port_provider) {}
mach_port_t ProcessMetrics::TaskForPid(ProcessHandle process) const {
mach_port_t task = MACH_PORT_NULL;
diff --git a/chromium/base/process/process_metrics_openbsd.cc b/chromium/base/process/process_metrics_openbsd.cc
index d8fbe7e3710..c863313233b 100644
--- a/chromium/base/process/process_metrics_openbsd.cc
+++ b/chromium/base/process/process_metrics_openbsd.cc
@@ -11,7 +11,6 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/sys_info.h"
namespace base {
@@ -112,7 +111,7 @@ static int GetProcessCPU(pid_t pid) {
return info.p_pctcpu;
}
-double ProcessMetrics::GetCPUUsage() {
+double ProcessMetrics::GetPlatformIndependentCPUUsage() {
TimeTicks time = TimeTicks::Now();
if (last_cpu_ == 0) {
@@ -140,7 +139,6 @@ double ProcessMetrics::GetCPUUsage() {
ProcessMetrics::ProcessMetrics(ProcessHandle process)
: process_(process),
- processor_count_(SysInfo::NumberOfProcessors()),
last_system_time_(0),
last_cpu_(0) {}
diff --git a/chromium/base/process/process_metrics_unittest.cc b/chromium/base/process/process_metrics_unittest.cc
index a09b6648382..2a187151e6a 100644
--- a/chromium/base/process/process_metrics_unittest.cc
+++ b/chromium/base/process/process_metrics_unittest.cc
@@ -361,15 +361,15 @@ TEST_F(SystemMetricsTest, ParseVmstat) {
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
-// Test that ProcessMetrics::GetCPUUsage() doesn't return negative values when
-// the number of threads running on the process decreases between two successive
-// calls to it.
+// Test that ProcessMetrics::GetPlatformIndependentCPUUsage() doesn't return
+// negative values when the number of threads running on the process decreases
+// between two successive calls to it.
TEST_F(SystemMetricsTest, TestNoNegativeCpuUsage) {
ProcessHandle handle = GetCurrentProcessHandle();
std::unique_ptr<ProcessMetrics> metrics(
ProcessMetrics::CreateProcessMetrics(handle));
- EXPECT_GE(metrics->GetCPUUsage(), 0.0);
+ EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
Thread thread1("thread1");
Thread thread2("thread2");
Thread thread3("thread3");
@@ -390,16 +390,16 @@ TEST_F(SystemMetricsTest, TestNoNegativeCpuUsage) {
thread2.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec2));
thread3.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec3));
- EXPECT_GE(metrics->GetCPUUsage(), 0.0);
+ EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
thread1.Stop();
- EXPECT_GE(metrics->GetCPUUsage(), 0.0);
+ EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
thread2.Stop();
- EXPECT_GE(metrics->GetCPUUsage(), 0.0);
+ EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
thread3.Stop();
- EXPECT_GE(metrics->GetCPUUsage(), 0.0);
+ EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
}
#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
diff --git a/chromium/base/process/process_metrics_win.cc b/chromium/base/process/process_metrics_win.cc
index 9de34496920..e5643ecb814 100644
--- a/chromium/base/process/process_metrics_win.cc
+++ b/chromium/base/process/process_metrics_win.cc
@@ -37,6 +37,11 @@ typedef NTSTATUS(WINAPI* NTQUERYSYSTEMINFORMATION)(
ProcessMetrics::~ProcessMetrics() { }
+size_t GetMaxFds() {
+ // Windows is only limited by the amount of physical memory.
+ return std::numeric_limits<size_t>::max();
+}
+
// static
std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
ProcessHandle process) {
@@ -279,7 +284,7 @@ static uint64_t FileTimeToUTC(const FILETIME& ftime) {
return li.QuadPart;
}
-double ProcessMetrics::GetCPUUsage() {
+double ProcessMetrics::GetPlatformIndependentCPUUsage() {
FILETIME creation_time;
FILETIME exit_time;
FILETIME kernel_time;
@@ -292,9 +297,7 @@ double ProcessMetrics::GetCPUUsage() {
// not yet received the notification.
return 0;
}
- int64_t system_time =
- (FileTimeToUTC(kernel_time) + FileTimeToUTC(user_time)) /
- processor_count_;
+ int64_t system_time = FileTimeToUTC(kernel_time) + FileTimeToUTC(user_time);
TimeTicks time = TimeTicks::Now();
if (last_system_time_ == 0) {
@@ -315,15 +318,14 @@ double ProcessMetrics::GetCPUUsage() {
last_system_time_ = system_time;
last_cpu_time_ = time;
- return static_cast<double>(system_time_delta * 100.0) / time_delta;
+ return static_cast<double>(system_time_delta * 100) / time_delta;
}
bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
return GetProcessIoCounters(process_.Get(), io_counters) != FALSE;
}
-ProcessMetrics::ProcessMetrics(ProcessHandle process)
- : processor_count_(SysInfo::NumberOfProcessors()), last_system_time_(0) {
+ProcessMetrics::ProcessMetrics(ProcessHandle process) : last_system_time_(0) {
if (process) {
HANDLE duplicate_handle;
BOOL result = ::DuplicateHandle(::GetCurrentProcess(), process,
diff --git a/chromium/base/process/process_posix.cc b/chromium/base/process/process_posix.cc
index 282923bd002..11f48f75acb 100644
--- a/chromium/base/process/process_posix.cc
+++ b/chromium/base/process/process_posix.cc
@@ -95,7 +95,6 @@ bool WaitpidWithTimeout(base::ProcessHandle handle,
static bool WaitForSingleNonChildProcess(base::ProcessHandle handle,
base::TimeDelta wait) {
DCHECK_GT(handle, 0);
- DCHECK_GT(wait, base::TimeDelta());
base::ScopedFD kq(kqueue());
if (!kq.is_valid()) {
@@ -129,7 +128,7 @@ static bool WaitForSingleNonChildProcess(base::ProcessHandle handle,
result = -1;
struct kevent event = {0};
- while (wait_forever || remaining_delta > base::TimeDelta()) {
+ do {
struct timespec remaining_timespec;
struct timespec* remaining_timespec_ptr;
if (wait_forever) {
@@ -149,7 +148,7 @@ static bool WaitForSingleNonChildProcess(base::ProcessHandle handle,
} else {
break;
}
- }
+ } while (wait_forever || remaining_delta > base::TimeDelta());
if (result < 0) {
DPLOG(ERROR) << "kevent (wait " << handle << ")";
@@ -182,10 +181,16 @@ static bool WaitForSingleNonChildProcess(base::ProcessHandle handle,
bool WaitForExitWithTimeoutImpl(base::ProcessHandle handle,
int* exit_code,
base::TimeDelta timeout) {
- base::ProcessHandle parent_pid = base::GetParentProcessId(handle);
- base::ProcessHandle our_pid = base::GetCurrentProcessHandle();
+ const base::ProcessHandle our_pid = base::GetCurrentProcessHandle();
+ if (handle == our_pid) {
+ // We won't be able to wait for ourselves to exit.
+ return false;
+ }
- if (parent_pid != our_pid) {
+ const base::ProcessHandle parent_pid = base::GetParentProcessId(handle);
+ const bool exited = (parent_pid < 0);
+
+ if (!exited && parent_pid != our_pid) {
#if defined(OS_MACOSX)
// On Mac we can wait on non child processes.
return WaitForSingleNonChildProcess(handle, timeout);
@@ -197,7 +202,7 @@ bool WaitForExitWithTimeoutImpl(base::ProcessHandle handle,
int status;
if (!WaitpidWithTimeout(handle, &status, timeout))
- return false;
+ return exited;
if (WIFSIGNALED(status)) {
if (exit_code)
*exit_code = -1;
@@ -208,7 +213,7 @@ bool WaitForExitWithTimeoutImpl(base::ProcessHandle handle,
*exit_code = WEXITSTATUS(status);
return true;
}
- return false;
+ return exited;
}
#endif // !defined(OS_NACL_NONSFI)
diff --git a/chromium/base/process/process_unittest.cc b/chromium/base/process/process_unittest.cc
index 8fcb9b92eb6..d9c2409fb16 100644
--- a/chromium/base/process/process_unittest.cc
+++ b/chromium/base/process/process_unittest.cc
@@ -287,6 +287,34 @@ TEST_F(ProcessTest, SetProcessBackgroundedSelf) {
EXPECT_EQ(old_priority, new_priority);
}
+// Consumers can use WaitForExitWithTimeout(base::TimeDelta(), nullptr) to check
+// whether the process is still running. This may not be safe because of the
+// potential reusing of the process id. So we won't export Process::IsRunning()
+// on all platforms. But for the controllable scenario in the test cases, the
+// behavior should be guaranteed.
+TEST_F(ProcessTest, CurrentProcessIsRunning) {
+ EXPECT_FALSE(Process::Current().WaitForExitWithTimeout(
+ base::TimeDelta(), nullptr));
+}
+
+#if defined(OS_MACOSX)
+// On Mac OSX, we can detect whether a non-child process is running.
+TEST_F(ProcessTest, PredefinedProcessIsRunning) {
+ // Process 1 is the /sbin/launchd, it should be always running.
+ EXPECT_FALSE(Process::Open(1).WaitForExitWithTimeout(
+ base::TimeDelta(), nullptr));
+}
+#endif
+
+TEST_F(ProcessTest, ChildProcessIsRunning) {
+ Process process(SpawnChild("SleepyChildProcess"));
+ EXPECT_FALSE(process.WaitForExitWithTimeout(
+ base::TimeDelta(), nullptr));
+ process.Terminate(0, true);
+ EXPECT_TRUE(process.WaitForExitWithTimeout(
+ base::TimeDelta(), nullptr));
+}
+
#if defined(OS_CHROMEOS)
// Tests that the function IsProcessBackgroundedCGroup() can parse the contents
diff --git a/chromium/base/process/process_util_unittest.cc b/chromium/base/process/process_util_unittest.cc
index 366ec4c2d8d..74c22505f49 100644
--- a/chromium/base/process/process_util_unittest.cc
+++ b/chromium/base/process/process_util_unittest.cc
@@ -64,9 +64,9 @@
#include "third_party/lss/linux_syscall_support.h"
#endif
#if defined(OS_FUCHSIA)
-#include <magenta/process.h>
-#include <magenta/processargs.h>
-#include <magenta/syscalls.h>
+#include <zircon/process.h>
+#include <zircon/processargs.h>
+#include <zircon/syscalls.h>
#endif
using base::FilePath;
@@ -742,27 +742,27 @@ TEST_F(ProcessUtilTest, FDRemappingIncludesStdio) {
#if defined(OS_FUCHSIA)
const uint16_t kStartupHandleId = 43;
MULTIPROCESS_TEST_MAIN(ProcessUtilsVerifyHandle) {
- mx_handle_t handle =
- mx_get_startup_handle(PA_HND(PA_USER0, kStartupHandleId));
- CHECK_NE(MX_HANDLE_INVALID, handle);
+ zx_handle_t handle =
+ zx_get_startup_handle(PA_HND(PA_USER0, kStartupHandleId));
+ CHECK_NE(ZX_HANDLE_INVALID, handle);
// Write to the pipe so the parent process can observe output.
size_t bytes_written = 0;
- mx_status_t result = mx_socket_write(handle, 0, &kPipeValue,
+ zx_status_t result = zx_socket_write(handle, 0, &kPipeValue,
sizeof(kPipeValue), &bytes_written);
- CHECK_EQ(MX_OK, result);
+ CHECK_EQ(ZX_OK, result);
CHECK_EQ(1u, bytes_written);
- CHECK_EQ(MX_OK, mx_handle_close(handle));
+ CHECK_EQ(ZX_OK, zx_handle_close(handle));
return 0;
}
TEST_F(ProcessUtilTest, LaunchWithHandleTransfer) {
// Create a pipe to pass to the child process.
- mx_handle_t handles[2];
- mx_status_t result =
- mx_socket_create(MX_SOCKET_STREAM, &handles[0], &handles[1]);
- ASSERT_EQ(MX_OK, result);
+ zx_handle_t handles[2];
+ zx_status_t result =
+ zx_socket_create(ZX_SOCKET_STREAM, &handles[0], &handles[1]);
+ ASSERT_EQ(ZX_OK, result);
// Launch the test process, and pass it one end of the pipe.
base::LaunchOptions options;
@@ -773,20 +773,20 @@ TEST_F(ProcessUtilTest, LaunchWithHandleTransfer) {
ASSERT_TRUE(process.IsValid());
// Read from the pipe to verify that the child received it.
- mx_signals_t signals = 0;
- result = mx_object_wait_one(handles[1], MX_SOCKET_READABLE,
- mx_deadline_after(MX_SEC(5)), &signals);
- EXPECT_EQ(MX_OK, result);
- EXPECT_TRUE(signals & MX_SOCKET_READABLE);
+ zx_signals_t signals = 0;
+ result = zx_object_wait_one(handles[1], ZX_SOCKET_READABLE,
+ zx_deadline_after(ZX_SEC(5)), &signals);
+ EXPECT_EQ(ZX_OK, result);
+ EXPECT_TRUE(signals & ZX_SOCKET_READABLE);
size_t bytes_read = 0;
char buf[16] = {0};
- result = mx_socket_read(handles[1], 0, buf, sizeof(buf), &bytes_read);
- EXPECT_EQ(MX_OK, result);
+ result = zx_socket_read(handles[1], 0, buf, sizeof(buf), &bytes_read);
+ EXPECT_EQ(ZX_OK, result);
EXPECT_EQ(1u, bytes_read);
EXPECT_EQ(kPipeValue, buf[0]);
- CHECK_EQ(MX_OK, mx_handle_close(handles[1]));
+ CHECK_EQ(ZX_OK, zx_handle_close(handles[1]));
int exit_code;
ASSERT_TRUE(process.WaitForExitWithTimeout(base::TimeDelta::FromSeconds(5),
@@ -982,12 +982,12 @@ TEST_F(ProcessUtilTest, GetParentProcessId) {
// TODO(port): port those unit tests.
bool IsProcessDead(base::ProcessHandle child) {
#if defined(OS_FUCHSIA)
- // ProcessHandle is an mx_handle_t, not a pid on Fuchsia, so waitpid() doesn't
+ // ProcessHandle is an zx_handle_t, not a pid on Fuchsia, so waitpid() doesn't
// make sense.
- mx_signals_t signals;
+ zx_signals_t signals;
// Timeout of 0 to check for termination, but non-blocking.
- if (mx_object_wait_one(child, MX_TASK_TERMINATED, 0, &signals) == MX_OK) {
- DCHECK(signals & MX_TASK_TERMINATED);
+ if (zx_object_wait_one(child, ZX_TASK_TERMINATED, 0, &signals) == ZX_OK) {
+ DCHECK(signals & ZX_TASK_TERMINATED);
return true;
}
return false;