kill_win.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright (c) 2013 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. #include "base/process/kill.h"
  5. #include <algorithm>
  6. #include <windows.h>
  7. #include <io.h>
  8. #include <stdint.h>
  9. #include "base/logging.h"
  10. #include "base/notreached.h"
  11. #include "base/process/memory.h"
  12. #include "base/process/process_iterator.h"
  13. namespace base {
  14. TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
  15. DCHECK(exit_code);
  16. DWORD tmp_exit_code = 0;
  17. if (!::GetExitCodeProcess(handle, &tmp_exit_code)) {
  18. DPLOG(FATAL) << "GetExitCodeProcess() failed";
  19. // This really is a random number. We haven't received any
  20. // information about the exit code, presumably because this
  21. // process doesn't have permission to get the exit code, or
  22. // because of some other cause for GetExitCodeProcess to fail
  23. // (MSDN docs don't give the possible failure error codes for
  24. // this function, so it could be anything). But we don't want
  25. // to leave exit_code uninitialized, since that could cause
  26. // random interpretations of the exit code. So we assume it
  27. // terminated "normally" in this case.
  28. *exit_code = win::kNormalTerminationExitCode;
  29. // Assume the child has exited normally if we can't get the exit
  30. // code.
  31. return TERMINATION_STATUS_NORMAL_TERMINATION;
  32. }
  33. if (tmp_exit_code == STILL_ACTIVE) {
  34. DWORD wait_result = WaitForSingleObject(handle, 0);
  35. if (wait_result == WAIT_TIMEOUT) {
  36. *exit_code = static_cast<int>(wait_result);
  37. return TERMINATION_STATUS_STILL_RUNNING;
  38. }
  39. if (wait_result == WAIT_FAILED) {
  40. DPLOG(ERROR) << "WaitForSingleObject() failed";
  41. } else {
  42. DCHECK_EQ(WAIT_OBJECT_0, wait_result);
  43. // Strange, the process used 0x103 (STILL_ACTIVE) as exit code.
  44. NOTREACHED();
  45. }
  46. return TERMINATION_STATUS_ABNORMAL_TERMINATION;
  47. }
  48. *exit_code = static_cast<int>(tmp_exit_code);
  49. // clang-format off
  50. switch (tmp_exit_code) {
  51. case win::kNormalTerminationExitCode:
  52. return TERMINATION_STATUS_NORMAL_TERMINATION;
  53. case win::kDebuggerInactiveExitCode: // STATUS_DEBUGGER_INACTIVE.
  54. case win::kKeyboardInterruptExitCode: // Control-C/end session.
  55. case win::kDebuggerTerminatedExitCode: // Debugger terminated process.
  56. case win::kProcessKilledExitCode: // Task manager kill.
  57. return TERMINATION_STATUS_PROCESS_WAS_KILLED;
  58. case win::kSandboxFatalMemoryExceeded: // Terminated process due to
  59. // exceeding the sandbox job
  60. // object memory limits.
  61. case win::kOomExceptionCode: // Ran out of memory.
  62. return TERMINATION_STATUS_OOM;
  63. // This exit code means the process failed an OS integrity check.
  64. // This is tested in ProcessMitigationsTest.* in sandbox.
  65. case win::kStatusInvalidImageHashExitCode:
  66. return TERMINATION_STATUS_INTEGRITY_FAILURE;
  67. default:
  68. // All other exit codes indicate crashes.
  69. return TERMINATION_STATUS_PROCESS_CRASHED;
  70. }
  71. // clang-format on
  72. }
  73. bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
  74. TimeDelta wait,
  75. const ProcessFilter* filter) {
  76. bool result = true;
  77. DWORD start_time = GetTickCount();
  78. NamedProcessIterator iter(executable_name, filter);
  79. for (const ProcessEntry* entry = iter.NextProcessEntry(); entry;
  80. entry = iter.NextProcessEntry()) {
  81. DWORD remaining_wait = static_cast<DWORD>(
  82. std::max(static_cast<int64_t>(0),
  83. wait.InMilliseconds() - (GetTickCount() - start_time)));
  84. HANDLE process = OpenProcess(SYNCHRONIZE,
  85. FALSE,
  86. entry->th32ProcessID);
  87. DWORD wait_result = WaitForSingleObject(process, remaining_wait);
  88. CloseHandle(process);
  89. result &= (wait_result == WAIT_OBJECT_0);
  90. }
  91. return result;
  92. }
  93. bool CleanupProcesses(const FilePath::StringType& executable_name,
  94. TimeDelta wait,
  95. int exit_code,
  96. const ProcessFilter* filter) {
  97. if (WaitForProcessesToExit(executable_name, wait, filter))
  98. return true;
  99. KillProcesses(executable_name, exit_code, filter);
  100. return false;
  101. }
  102. } // namespace base