summaryrefslogtreecommitdiffstats
path: root/chromium/base/process/process_win.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/base/process/process_win.cc')
-rw-r--r--chromium/base/process/process_win.cc96
1 files changed, 85 insertions, 11 deletions
diff --git a/chromium/base/process/process_win.cc b/chromium/base/process/process_win.cc
index 05041b20dda..0d312a35990 100644
--- a/chromium/base/process/process_win.cc
+++ b/chromium/base/process/process_win.cc
@@ -6,8 +6,18 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/metrics/field_trial.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/process/kill.h"
#include "base/win/windows_version.h"
+namespace {
+
+DWORD kBasicProcessAccess =
+ PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | SYNCHRONIZE;
+
+} // namespace
+
namespace base {
Process::Process(ProcessHandle handle)
@@ -22,6 +32,9 @@ Process::Process(RValue other)
other.object->Close();
}
+Process::~Process() {
+}
+
Process& Process::operator=(RValue other) {
if (this != other.object) {
process_.Set(other.object->process_.Take());
@@ -39,6 +52,34 @@ Process Process::Current() {
}
// static
+Process Process::Open(ProcessId pid) {
+ return Process(::OpenProcess(kBasicProcessAccess, FALSE, pid));
+}
+
+// static
+Process Process::OpenWithExtraPrivileges(ProcessId pid) {
+ DWORD access = kBasicProcessAccess | PROCESS_DUP_HANDLE | PROCESS_VM_READ;
+ return Process(::OpenProcess(access, FALSE, pid));
+}
+
+// static
+Process Process::OpenWithAccess(ProcessId pid, DWORD desired_access) {
+ return Process(::OpenProcess(desired_access, FALSE, pid));
+}
+
+// static
+Process Process::DeprecatedGetProcessFromHandle(ProcessHandle handle) {
+ DCHECK_NE(handle, ::GetCurrentProcess());
+ ProcessHandle out_handle;
+ if (!::DuplicateHandle(GetCurrentProcess(), handle,
+ GetCurrentProcess(), &out_handle,
+ 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+ return Process();
+ }
+ return Process(out_handle);
+}
+
+// static
bool Process::CanBackgroundProcesses() {
return true;
}
@@ -68,7 +109,7 @@ Process Process::Duplicate() const {
return Process(out_handle);
}
-ProcessId Process::pid() const {
+ProcessId Process::Pid() const {
DCHECK(IsValid());
return GetProcId(Handle());
}
@@ -85,17 +126,36 @@ void Process::Close() {
process_.Close();
}
-void Process::Terminate(int result_code) {
+bool Process::Terminate(int exit_code, bool wait) const {
DCHECK(IsValid());
+ bool result = (::TerminateProcess(Handle(), exit_code) != FALSE);
+ if (result && wait) {
+ // The process may not end immediately due to pending I/O
+ if (::WaitForSingleObject(Handle(), 60 * 1000) != WAIT_OBJECT_0)
+ DPLOG(ERROR) << "Error waiting for process exit";
+ } else if (!result) {
+ DPLOG(ERROR) << "Unable to terminate process";
+ }
+ return result;
+}
+
+bool Process::WaitForExit(int* exit_code) {
+ return WaitForExitWithTimeout(TimeDelta::FromMilliseconds(INFINITE),
+ exit_code);
+}
- // Call NtTerminateProcess directly, without going through the import table,
- // which might have been hooked with a buggy replacement by third party
- // software. http://crbug.com/81449.
- HMODULE module = GetModuleHandle(L"ntdll.dll");
- typedef UINT (WINAPI *TerminateProcessPtr)(HANDLE handle, UINT code);
- TerminateProcessPtr terminate_process = reinterpret_cast<TerminateProcessPtr>(
- GetProcAddress(module, "NtTerminateProcess"));
- terminate_process(Handle(), result_code);
+bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) {
+ // Limit timeout to INFINITE.
+ DWORD timeout_ms = saturated_cast<DWORD>(timeout.InMilliseconds());
+ if (::WaitForSingleObject(Handle(), timeout_ms) != WAIT_OBJECT_0)
+ return false;
+
+ DWORD temp_code; // Don't clobber out-parameters in case of failure.
+ if (!::GetExitCodeProcess(Handle(), &temp_code))
+ return false;
+
+ *exit_code = temp_code;
+ return true;
}
bool Process::IsProcessBackgrounded() const {
@@ -117,7 +177,21 @@ bool Process::SetProcessBackgrounded(bool value) {
priority = value ? PROCESS_MODE_BACKGROUND_BEGIN :
PROCESS_MODE_BACKGROUND_END;
} else {
- priority = value ? BELOW_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS;
+ // Experiment (http://crbug.com/458594) with using IDLE_PRIORITY_CLASS as a
+ // background priority for background renderers (this code path is
+ // technically for more than just the renderers but they're the only use
+ // case in practice and experimenting here direclty is thus easier -- plus
+ // it doesn't really hurt as above we already state our intent of using
+ // PROCESS_MODE_BACKGROUND_BEGIN if available which is essentially
+ // IDLE_PRIORITY_CLASS plus lowered IO priority). Enabled by default in the
+ // asbence of field trials to get coverage on the perf waterfall.
+ DWORD background_priority = IDLE_PRIORITY_CLASS;
+ base::FieldTrial* trial =
+ base::FieldTrialList::Find("BackgroundRendererProcesses");
+ if (trial && trial->group_name() == "AllowBelowNormalFromBrowser")
+ background_priority = BELOW_NORMAL_PRIORITY_CLASS;
+
+ priority = value ? background_priority : NORMAL_PRIORITY_CLASS;
}
return (::SetPriorityClass(Handle(), priority) != 0);