blob: 7a664429bcd305b10da8c7317700f9124742f3b8 [file] [log] [blame]
[email protected]307af212013-07-10 18:36:091// 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
5#include "base/process/kill.h"
6
Wezc18a57c2018-04-02 20:20:147#include <algorithm>
8
[email protected]307af212013-07-10 18:36:099#include <windows.h>
avibeced7c2015-12-24 06:47:5910#include <io.h>
11#include <stdint.h>
[email protected]307af212013-07-10 18:36:0912
[email protected]307af212013-07-10 18:36:0913#include "base/logging.h"
avibeced7c2015-12-24 06:47:5914#include "base/macros.h"
wfhfa40c2722016-07-26 01:12:2815#include "base/process/memory.h"
[email protected]307af212013-07-10 18:36:0916#include "base/process/process_iterator.h"
[email protected]307af212013-07-10 18:36:0917
18namespace base {
19
[email protected]307af212013-07-10 18:36:0920TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
Wez05c2c682017-08-17 16:20:1121 DCHECK(exit_code);
22
[email protected]307af212013-07-10 18:36:0923 DWORD tmp_exit_code = 0;
24
25 if (!::GetExitCodeProcess(handle, &tmp_exit_code)) {
[email protected]ad8cfa92014-05-21 20:06:2326 DPLOG(FATAL) << "GetExitCodeProcess() failed";
Wez05c2c682017-08-17 16:20:1127
28 // This really is a random number. We haven't received any
29 // information about the exit code, presumably because this
30 // process doesn't have permission to get the exit code, or
31 // because of some other cause for GetExitCodeProcess to fail
32 // (MSDN docs don't give the possible failure error codes for
33 // this function, so it could be anything). But we don't want
34 // to leave exit_code uninitialized, since that could cause
35 // random interpretations of the exit code. So we assume it
36 // terminated "normally" in this case.
Bruce Dawsonec0158512017-11-16 09:10:4037 *exit_code = win::kNormalTerminationExitCode;
Wez05c2c682017-08-17 16:20:1138
[email protected]307af212013-07-10 18:36:0939 // Assume the child has exited normally if we can't get the exit
40 // code.
41 return TERMINATION_STATUS_NORMAL_TERMINATION;
42 }
43 if (tmp_exit_code == STILL_ACTIVE) {
44 DWORD wait_result = WaitForSingleObject(handle, 0);
45 if (wait_result == WAIT_TIMEOUT) {
Wez05c2c682017-08-17 16:20:1146 *exit_code = wait_result;
[email protected]307af212013-07-10 18:36:0947 return TERMINATION_STATUS_STILL_RUNNING;
48 }
49
50 if (wait_result == WAIT_FAILED) {
[email protected]ad8cfa92014-05-21 20:06:2351 DPLOG(ERROR) << "WaitForSingleObject() failed";
[email protected]307af212013-07-10 18:36:0952 } else {
53 DCHECK_EQ(WAIT_OBJECT_0, wait_result);
54
55 // Strange, the process used 0x103 (STILL_ACTIVE) as exit code.
56 NOTREACHED();
57 }
58
59 return TERMINATION_STATUS_ABNORMAL_TERMINATION;
60 }
61
Wez05c2c682017-08-17 16:20:1162 *exit_code = tmp_exit_code;
[email protected]307af212013-07-10 18:36:0963
64 switch (tmp_exit_code) {
Bruce Dawsonec0158512017-11-16 09:10:4065 case win::kNormalTerminationExitCode:
[email protected]307af212013-07-10 18:36:0966 return TERMINATION_STATUS_NORMAL_TERMINATION;
Bruce Dawsonec0158512017-11-16 09:10:4067 case win::kDebuggerInactiveExitCode: // STATUS_DEBUGGER_INACTIVE.
68 case win::kKeyboardInterruptExitCode: // Control-C/end session.
69 case win::kDebuggerTerminatedExitCode: // Debugger terminated process.
70 case win::kProcessKilledExitCode: // Task manager kill.
[email protected]307af212013-07-10 18:36:0971 return TERMINATION_STATUS_PROCESS_WAS_KILLED;
Bruce Dawsonec0158512017-11-16 09:10:4072 case win::kSandboxFatalMemoryExceeded: // Terminated process due to
73 // exceeding the sandbox job
74 // object memory limits.
75 case win::kOomExceptionCode: // Ran out of memory.
wfhfa40c2722016-07-26 01:12:2876 return TERMINATION_STATUS_OOM;
[email protected]307af212013-07-10 18:36:0977 default:
78 // All other exit codes indicate crashes.
79 return TERMINATION_STATUS_PROCESS_CRASHED;
80 }
81}
82
[email protected]307af212013-07-10 18:36:0983bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
rvargas2f70a152015-02-24 00:28:1184 TimeDelta wait,
[email protected]307af212013-07-10 18:36:0985 const ProcessFilter* filter) {
[email protected]307af212013-07-10 18:36:0986 bool result = true;
87 DWORD start_time = GetTickCount();
88
89 NamedProcessIterator iter(executable_name, filter);
[email protected]ed8e57da2014-07-03 07:03:3990 for (const ProcessEntry* entry = iter.NextProcessEntry(); entry;
91 entry = iter.NextProcessEntry()) {
avibeced7c2015-12-24 06:47:5992 DWORD remaining_wait = static_cast<DWORD>(
93 std::max(static_cast<int64_t>(0),
94 wait.InMilliseconds() - (GetTickCount() - start_time)));
brucedawsond3509432015-09-18 18:28:1395 HANDLE process = OpenProcess(SYNCHRONIZE,
96 FALSE,
97 entry->th32ProcessID);
98 DWORD wait_result = WaitForSingleObject(process, remaining_wait);
99 CloseHandle(process);
[email protected]ed8e57da2014-07-03 07:03:39100 result &= (wait_result == WAIT_OBJECT_0);
[email protected]307af212013-07-10 18:36:09101 }
102
103 return result;
104}
105
[email protected]307af212013-07-10 18:36:09106bool CleanupProcesses(const FilePath::StringType& executable_name,
rvargas2f70a152015-02-24 00:28:11107 TimeDelta wait,
[email protected]307af212013-07-10 18:36:09108 int exit_code,
109 const ProcessFilter* filter) {
[email protected]ed8e57da2014-07-03 07:03:39110 if (WaitForProcessesToExit(executable_name, wait, filter))
111 return true;
112 KillProcesses(executable_name, exit_code, filter);
113 return false;
[email protected]307af212013-07-10 18:36:09114}
115
[email protected]307af212013-07-10 18:36:09116} // namespace base