OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/process/process.h" | 5 #include "base/process/process.h" |
6 | 6 |
7 #include <sys/resource.h> | 7 #include <sys/resource.h> |
8 #include <sys/wait.h> | 8 #include <sys/wait.h> |
9 | 9 |
10 #include "base/files/scoped_file.h" | 10 #include "base/files/scoped_file.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/posix/eintr_wrapper.h" | 12 #include "base/posix/eintr_wrapper.h" |
13 #include "base/process/kill.h" | 13 #include "base/process/kill.h" |
| 14 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
14 | 15 |
15 #if defined(OS_MACOSX) | 16 #if defined(OS_MACOSX) |
16 #include <sys/event.h> | 17 #include <sys/event.h> |
17 #endif | 18 #endif |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 #if !defined(OS_NACL_NONSFI) | 22 #if !defined(OS_NACL_NONSFI) |
22 | 23 |
23 bool WaitpidWithTimeout(base::ProcessHandle handle, | 24 bool WaitpidWithTimeout(base::ProcessHandle handle, |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 } | 204 } |
204 #endif // !defined(OS_NACL_NONSFI) | 205 #endif // !defined(OS_NACL_NONSFI) |
205 | 206 |
206 } // namespace | 207 } // namespace |
207 | 208 |
208 namespace base { | 209 namespace base { |
209 | 210 |
210 Process::Process(ProcessHandle handle) : process_(handle) { | 211 Process::Process(ProcessHandle handle) : process_(handle) { |
211 } | 212 } |
212 | 213 |
| 214 Process::~Process() { |
| 215 } |
| 216 |
213 Process::Process(RValue other) | 217 Process::Process(RValue other) |
214 : process_(other.object->process_) { | 218 : process_(other.object->process_) { |
215 other.object->Close(); | 219 other.object->Close(); |
216 } | 220 } |
217 | 221 |
218 Process& Process::operator=(RValue other) { | 222 Process& Process::operator=(RValue other) { |
219 if (this != other.object) { | 223 if (this != other.object) { |
220 process_ = other.object->process_; | 224 process_ = other.object->process_; |
221 other.object->Close(); | 225 other.object->Close(); |
222 } | 226 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 return process_ == GetCurrentProcessHandle(); | 284 return process_ == GetCurrentProcessHandle(); |
281 } | 285 } |
282 | 286 |
283 void Process::Close() { | 287 void Process::Close() { |
284 process_ = kNullProcessHandle; | 288 process_ = kNullProcessHandle; |
285 // if the process wasn't terminated (so we waited) or the state | 289 // if the process wasn't terminated (so we waited) or the state |
286 // wasn't already collected w/ a wait from process_utils, we're gonna | 290 // wasn't already collected w/ a wait from process_utils, we're gonna |
287 // end up w/ a zombie when it does finally exit. | 291 // end up w/ a zombie when it does finally exit. |
288 } | 292 } |
289 | 293 |
290 bool Process::Terminate(int result_code, bool wait) const { | 294 #if !defined(OS_NACL_NONSFI) |
| 295 bool Process::Terminate(int exit_code, bool wait) const { |
291 // result_code isn't supportable. | 296 // result_code isn't supportable. |
292 DCHECK(IsValid()); | 297 DCHECK(IsValid()); |
293 // We don't wait here. It's the responsibility of other code to reap the | 298 DCHECK_GT(process_, 1); |
294 // child. | 299 bool result = kill(process_, SIGTERM) == 0; |
295 // TODO(rvargas) crbug/417532: Move the implementation here. | 300 if (result && wait) { |
296 return KillProcess(process_, result_code, wait); | 301 int tries = 60; |
| 302 |
| 303 if (RunningOnValgrind()) { |
| 304 // Wait for some extra time when running under Valgrind since the child |
| 305 // processes may take some time doing leak checking. |
| 306 tries *= 2; |
| 307 } |
| 308 |
| 309 unsigned sleep_ms = 4; |
| 310 |
| 311 // The process may not end immediately due to pending I/O |
| 312 bool exited = false; |
| 313 while (tries-- > 0) { |
| 314 pid_t pid = HANDLE_EINTR(waitpid(process_, NULL, WNOHANG)); |
| 315 if (pid == process_) { |
| 316 exited = true; |
| 317 break; |
| 318 } |
| 319 if (pid == -1) { |
| 320 if (errno == ECHILD) { |
| 321 // The wait may fail with ECHILD if another process also waited for |
| 322 // the same pid, causing the process state to get cleaned up. |
| 323 exited = true; |
| 324 break; |
| 325 } |
| 326 DPLOG(ERROR) << "Error waiting for process " << process_; |
| 327 } |
| 328 |
| 329 usleep(sleep_ms * 1000); |
| 330 const unsigned kMaxSleepMs = 1000; |
| 331 if (sleep_ms < kMaxSleepMs) |
| 332 sleep_ms *= 2; |
| 333 } |
| 334 |
| 335 // If we're waiting and the child hasn't died by now, force it |
| 336 // with a SIGKILL. |
| 337 if (!exited) |
| 338 result = kill(process_, SIGKILL) == 0; |
| 339 } |
| 340 |
| 341 if (!result) |
| 342 DPLOG(ERROR) << "Unable to terminate process " << process_; |
| 343 |
| 344 return result; |
297 } | 345 } |
| 346 #endif // !defined(OS_NACL_NONSFI) |
298 | 347 |
299 bool Process::WaitForExit(int* exit_code) { | 348 bool Process::WaitForExit(int* exit_code) { |
300 return WaitForExitWithTimeout(TimeDelta::Max(), exit_code); | 349 return WaitForExitWithTimeout(TimeDelta::Max(), exit_code); |
301 } | 350 } |
302 | 351 |
303 bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) { | 352 bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) { |
304 return WaitForExitWithTimeoutImpl(Handle(), exit_code, timeout); | 353 return WaitForExitWithTimeoutImpl(Handle(), exit_code, timeout); |
305 } | 354 } |
306 | 355 |
307 #if !defined(OS_LINUX) | 356 #if !defined(OS_LINUX) |
(...skipping 11 matching lines...) Expand all Loading... |
319 return false; | 368 return false; |
320 } | 369 } |
321 #endif // !defined(OS_LINUX) | 370 #endif // !defined(OS_LINUX) |
322 | 371 |
323 int Process::GetPriority() const { | 372 int Process::GetPriority() const { |
324 DCHECK(IsValid()); | 373 DCHECK(IsValid()); |
325 return getpriority(PRIO_PROCESS, process_); | 374 return getpriority(PRIO_PROCESS, process_); |
326 } | 375 } |
327 | 376 |
328 } // namespace base | 377 } // namespace base |
OLD | NEW |