| 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 |