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