Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: base/process/process_win.cc

Issue 1647803004: Move base to DEPS (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/process/process_util_unittest.cc ('k') | base/profiler/alternate_timer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/process/process.h"
6
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/numerics/safe_conversions.h"
11 #include "base/process/kill.h"
12 #include "base/strings/string_util.h"
13 #include "base/win/windows_version.h"
14
15 namespace {
16
17 DWORD kBasicProcessAccess =
18 PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | SYNCHRONIZE;
19
20 } // namespace
21
22 namespace base {
23
24 Process::Process(ProcessHandle handle)
25 : is_current_process_(false),
26 process_(handle) {
27 CHECK_NE(handle, ::GetCurrentProcess());
28 }
29
30 Process::Process(RValue other)
31 : is_current_process_(other.object->is_current_process_),
32 process_(other.object->process_.Take()) {
33 other.object->Close();
34 }
35
36 Process::~Process() {
37 }
38
39 Process& Process::operator=(RValue other) {
40 if (this != other.object) {
41 process_.Set(other.object->process_.Take());
42 is_current_process_ = other.object->is_current_process_;
43 other.object->Close();
44 }
45 return *this;
46 }
47
48 // static
49 Process Process::Current() {
50 Process process;
51 process.is_current_process_ = true;
52 return process.Pass();
53 }
54
55 // static
56 Process Process::Open(ProcessId pid) {
57 return Process(::OpenProcess(kBasicProcessAccess, FALSE, pid));
58 }
59
60 // static
61 Process Process::OpenWithExtraPrivileges(ProcessId pid) {
62 DWORD access = kBasicProcessAccess | PROCESS_DUP_HANDLE | PROCESS_VM_READ;
63 return Process(::OpenProcess(access, FALSE, pid));
64 }
65
66 // static
67 Process Process::OpenWithAccess(ProcessId pid, DWORD desired_access) {
68 return Process(::OpenProcess(desired_access, FALSE, pid));
69 }
70
71 // static
72 Process Process::DeprecatedGetProcessFromHandle(ProcessHandle handle) {
73 DCHECK_NE(handle, ::GetCurrentProcess());
74 ProcessHandle out_handle;
75 if (!::DuplicateHandle(GetCurrentProcess(), handle,
76 GetCurrentProcess(), &out_handle,
77 0, FALSE, DUPLICATE_SAME_ACCESS)) {
78 return Process();
79 }
80 return Process(out_handle);
81 }
82
83 // static
84 bool Process::CanBackgroundProcesses() {
85 return true;
86 }
87
88 bool Process::IsValid() const {
89 return process_.IsValid() || is_current();
90 }
91
92 ProcessHandle Process::Handle() const {
93 return is_current_process_ ? GetCurrentProcess() : process_.Get();
94 }
95
96 Process Process::Duplicate() const {
97 if (is_current())
98 return Current();
99
100 ProcessHandle out_handle;
101 if (!IsValid() || !::DuplicateHandle(GetCurrentProcess(),
102 Handle(),
103 GetCurrentProcess(),
104 &out_handle,
105 0,
106 FALSE,
107 DUPLICATE_SAME_ACCESS)) {
108 return Process();
109 }
110 return Process(out_handle);
111 }
112
113 ProcessId Process::Pid() const {
114 DCHECK(IsValid());
115 return GetProcId(Handle());
116 }
117
118 bool Process::is_current() const {
119 return is_current_process_;
120 }
121
122 void Process::Close() {
123 is_current_process_ = false;
124 if (!process_.IsValid())
125 return;
126
127 process_.Close();
128 }
129
130 bool Process::Terminate(int exit_code, bool wait) const {
131 DCHECK(IsValid());
132 bool result = (::TerminateProcess(Handle(), exit_code) != FALSE);
133 if (result && wait) {
134 // The process may not end immediately due to pending I/O
135 if (::WaitForSingleObject(Handle(), 60 * 1000) != WAIT_OBJECT_0)
136 DPLOG(ERROR) << "Error waiting for process exit";
137 } else if (!result) {
138 DPLOG(ERROR) << "Unable to terminate process";
139 }
140 return result;
141 }
142
143 bool Process::WaitForExit(int* exit_code) {
144 return WaitForExitWithTimeout(TimeDelta::FromMilliseconds(INFINITE),
145 exit_code);
146 }
147
148 bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) {
149 // Limit timeout to INFINITE.
150 DWORD timeout_ms = saturated_cast<DWORD>(timeout.InMilliseconds());
151 if (::WaitForSingleObject(Handle(), timeout_ms) != WAIT_OBJECT_0)
152 return false;
153
154 DWORD temp_code; // Don't clobber out-parameters in case of failure.
155 if (!::GetExitCodeProcess(Handle(), &temp_code))
156 return false;
157
158 if (exit_code)
159 *exit_code = temp_code;
160 return true;
161 }
162
163 bool Process::IsProcessBackgrounded() const {
164 DCHECK(IsValid());
165 DWORD priority = GetPriority();
166 if (priority == 0)
167 return false; // Failure case.
168 return ((priority == BELOW_NORMAL_PRIORITY_CLASS) ||
169 (priority == IDLE_PRIORITY_CLASS));
170 }
171
172 bool Process::SetProcessBackgrounded(bool value) {
173 DCHECK(IsValid());
174 // Vista and above introduce a real background mode, which not only
175 // sets the priority class on the threads but also on the IO generated
176 // by it. Unfortunately it can only be set for the calling process.
177 DWORD priority;
178 if ((base::win::GetVersion() >= base::win::VERSION_VISTA) && (is_current())) {
179 priority = value ? PROCESS_MODE_BACKGROUND_BEGIN :
180 PROCESS_MODE_BACKGROUND_END;
181 } else {
182 // Experiment (http://crbug.com/458594) with using IDLE_PRIORITY_CLASS as a
183 // background priority for background renderers (this code path is
184 // technically for more than just the renderers but they're the only use
185 // case in practice and experimenting here direclty is thus easier -- plus
186 // it doesn't really hurt as above we already state our intent of using
187 // PROCESS_MODE_BACKGROUND_BEGIN if available which is essentially
188 // IDLE_PRIORITY_CLASS plus lowered IO priority). Enabled by default in the
189 // asbence of field trials to get coverage on the perf waterfall.
190 DWORD background_priority = IDLE_PRIORITY_CLASS;
191 base::FieldTrial* trial =
192 base::FieldTrialList::Find("BackgroundRendererProcesses");
193 if (trial && StartsWith(trial->group_name(), "AllowBelowNormalFromBrowser",
194 CompareCase::SENSITIVE)) {
195 background_priority = BELOW_NORMAL_PRIORITY_CLASS;
196 }
197
198 priority = value ? background_priority : NORMAL_PRIORITY_CLASS;
199 }
200
201 return (::SetPriorityClass(Handle(), priority) != 0);
202 }
203
204 int Process::GetPriority() const {
205 DCHECK(IsValid());
206 return ::GetPriorityClass(Handle());
207 }
208
209 } // namespace base
OLDNEW
« no previous file with comments | « base/process/process_util_unittest.cc ('k') | base/profiler/alternate_timer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698