| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_util.h" | 5 #include "base/process_util.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <io.h> | 8 #include <io.h> |
| 9 #include <windows.h> | 9 #include <windows.h> |
| 10 #include <userenv.h> | 10 #include <userenv.h> |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 if (result && wait) { | 387 if (result && wait) { |
| 388 // The process may not end immediately due to pending I/O | 388 // The process may not end immediately due to pending I/O |
| 389 if (WAIT_OBJECT_0 != WaitForSingleObject(process, 60 * 1000)) | 389 if (WAIT_OBJECT_0 != WaitForSingleObject(process, 60 * 1000)) |
| 390 DLOG(ERROR) << "Error waiting for process exit: " << GetLastError(); | 390 DLOG(ERROR) << "Error waiting for process exit: " << GetLastError(); |
| 391 } else if (!result) { | 391 } else if (!result) { |
| 392 DLOG(ERROR) << "Unable to terminate process: " << GetLastError(); | 392 DLOG(ERROR) << "Unable to terminate process: " << GetLastError(); |
| 393 } | 393 } |
| 394 return result; | 394 return result; |
| 395 } | 395 } |
| 396 | 396 |
| 397 bool DidProcessCrash(bool* child_exited, ProcessHandle handle) { | 397 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) { |
| 398 DWORD exitcode = 0; | 398 DWORD tmp_exit_code = 0; |
| 399 | 399 |
| 400 if (!::GetExitCodeProcess(handle, &exitcode)) { | 400 if (!::GetExitCodeProcess(handle, &tmp_exit_code)) { |
| 401 NOTREACHED(); | 401 NOTREACHED(); |
| 402 // Assume the child has exited. | 402 if (exit_code) { |
| 403 if (child_exited) | 403 // This really is a random number. We haven't received any |
| 404 *child_exited = true; | 404 // information about the exit code, presumably because this |
| 405 return false; | 405 // process doesn't have permission to get the exit code, or |
| 406 // because of some other cause for GetExitCodeProcess to fail |
| 407 // (MSDN docs don't give the possible failure error codes for |
| 408 // this function, so it could be anything). But we don't want |
| 409 // to leave exit_code uninitialized, since that could cause |
| 410 // random interpretations of the exit code. So we assume it |
| 411 // terminated "normally" in this case. |
| 412 *exit_code = TERMINATION_STATUS_NORMAL_TERMINATION; |
| 413 } |
| 414 // Assume the child has exited normally if we can't get the exit |
| 415 // code. |
| 416 return TERMINATION_STATUS_NORMAL_TERMINATION; |
| 406 } | 417 } |
| 407 if (exitcode == STILL_ACTIVE) { | 418 if (tmp_exit_code == STILL_ACTIVE) { |
| 408 DWORD wait_result = WaitForSingleObject(handle, 0); | 419 DWORD wait_result = WaitForSingleObject(handle, 0); |
| 409 if (wait_result == WAIT_TIMEOUT) { | 420 if (wait_result == WAIT_TIMEOUT) { |
| 410 if (child_exited) | 421 if (exit_code) |
| 411 *child_exited = false; | 422 *exit_code = wait_result; |
| 412 return false; | 423 return TERMINATION_STATUS_STILL_RUNNING; |
| 413 } | 424 } |
| 414 | 425 |
| 415 DCHECK_EQ(WAIT_OBJECT_0, wait_result); | 426 DCHECK_EQ(WAIT_OBJECT_0, wait_result); |
| 416 | 427 |
| 417 // Strange, the process used 0x103 (STILL_ACTIVE) as exit code. | 428 // Strange, the process used 0x103 (STILL_ACTIVE) as exit code. |
| 418 NOTREACHED(); | 429 NOTREACHED(); |
| 419 | 430 |
| 420 return false; | 431 return TERMINATION_STATUS_ABNORMAL_TERMINATION; |
| 421 } | 432 } |
| 422 | 433 |
| 423 // We're sure the child has exited. | 434 if (exit_code) |
| 424 if (child_exited) | 435 *exit_code = tmp_exit_code; |
| 425 *child_exited = true; | |
| 426 | 436 |
| 427 // Warning, this is not generic code; it heavily depends on the way | 437 // Warning, this is not generic code; it heavily depends on the way |
| 428 // the rest of the code kills a process. | 438 // the rest of the code kills a process. |
| 429 | 439 |
| 430 if (exitcode == PROCESS_END_NORMAL_TERMINATION || | 440 switch (tmp_exit_code) { |
| 431 exitcode == PROCESS_END_KILLED_BY_USER || | 441 case PROCESS_END_NORMAL_TERMINATION: |
| 432 exitcode == PROCESS_END_PROCESS_WAS_HUNG || | 442 return TERMINATION_STATUS_NORMAL_TERMINATION; |
| 433 exitcode == 0xC0000354 || // STATUS_DEBUGGER_INACTIVE. | 443 case 0xC0000354: // STATUS_DEBUGGER_INACTIVE. |
| 434 exitcode == 0xC000013A || // Control-C/end session. | 444 case 0xC000013A: // Control-C/end session. |
| 435 exitcode == 0x40010004) { // Debugger terminated process/end session. | 445 case 0x40010004: // Debugger terminated process/end session. |
| 436 return false; | 446 case PROCESS_END_PROCESS_WAS_KILLED: // Task manager kill. |
| 447 return TERMINATION_STATUS_PROCESS_WAS_KILLED; |
| 448 case PROCESS_END_PROCESS_WAS_HUNG: |
| 449 return TERMINATION_STATUS_PROCESS_WAS_HUNG; |
| 450 default: |
| 451 // All other exit codes indicate crashes. |
| 452 return TERMINATION_STATUS_PROCESS_CRASHED; |
| 437 } | 453 } |
| 438 | |
| 439 // All other exit codes indicate crashes. | |
| 440 return true; | |
| 441 } | 454 } |
| 442 | 455 |
| 443 bool WaitForExitCode(ProcessHandle handle, int* exit_code) { | 456 bool WaitForExitCode(ProcessHandle handle, int* exit_code) { |
| 444 bool success = WaitForExitCodeWithTimeout(handle, exit_code, INFINITE); | 457 bool success = WaitForExitCodeWithTimeout(handle, exit_code, INFINITE); |
| 445 if (!success) | 458 if (!success) |
| 446 CloseProcessHandle(handle); | 459 CloseProcessHandle(handle); |
| 447 return success; | 460 return success; |
| 448 } | 461 } |
| 449 | 462 |
| 450 bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, | 463 bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, |
| (...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 | 900 |
| 888 PERFORMANCE_INFORMATION info; | 901 PERFORMANCE_INFORMATION info; |
| 889 if (!InternalGetPerformanceInfo(&info, sizeof(info))) { | 902 if (!InternalGetPerformanceInfo(&info, sizeof(info))) { |
| 890 LOG(ERROR) << "Failed to fetch internal performance info."; | 903 LOG(ERROR) << "Failed to fetch internal performance info."; |
| 891 return 0; | 904 return 0; |
| 892 } | 905 } |
| 893 return (info.CommitTotal * system_info.dwPageSize) / 1024; | 906 return (info.CommitTotal * system_info.dwPageSize) / 1024; |
| 894 } | 907 } |
| 895 | 908 |
| 896 } // namespace base | 909 } // namespace base |
| OLD | NEW |