• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // This file contains routines to kill processes and get the exit code and
6 // termination status.
7 
8 #ifndef BASE_PROCESS_KILL_H_
9 #define BASE_PROCESS_KILL_H_
10 
11 #include "base/base_export.h"
12 #include "base/files/file_path.h"
13 #include "base/process/process.h"
14 #include "base/process/process_handle.h"
15 #include "base/time/time.h"
16 #include "build/build_config.h"
17 
18 namespace base {
19 
20 class ProcessFilter;
21 
22 #if BUILDFLAG(IS_WIN)
23 namespace win {
24 
25 // See definition in sandbox/win/src/sandbox_types.h
26 const DWORD kSandboxFatalMemoryExceeded = 7012;
27 
28 // Exit codes with special meanings on Windows.
29 const DWORD kNormalTerminationExitCode = 0;
30 const DWORD kDebuggerInactiveExitCode = 0xC0000354;
31 const DWORD kKeyboardInterruptExitCode = 0xC000013A;
32 const DWORD kDebuggerTerminatedExitCode = 0x40010004;
33 const DWORD kStatusInvalidImageHashExitCode = 0xC0000428;
34 
35 // This exit code is used by the Windows task manager when it kills a
36 // process.  It's value is obviously not that unique, and it's
37 // surprising to me that the task manager uses this value, but it
38 // seems to be common practice on Windows to test for it as an
39 // indication that the task manager has killed something if the
40 // process goes away.
41 const DWORD kProcessKilledExitCode = 1;
42 
43 }  // namespace win
44 
45 #endif  // BUILDFLAG(IS_WIN)
46 
47 // Return status values from GetTerminationStatus.  Don't use these as
48 // exit code arguments to KillProcess*(), use platform/application
49 // specific values instead.
50 enum TerminationStatus {
51   // clang-format off
52   TERMINATION_STATUS_NORMAL_TERMINATION,   // zero exit status
53   TERMINATION_STATUS_ABNORMAL_TERMINATION, // non-zero exit status
54   TERMINATION_STATUS_PROCESS_WAS_KILLED,   // e.g. SIGKILL or task manager kill
55   TERMINATION_STATUS_PROCESS_CRASHED,      // e.g. Segmentation fault
56   TERMINATION_STATUS_STILL_RUNNING,        // child hasn't exited yet
57 #if BUILDFLAG(IS_CHROMEOS)
58   // Used for the case when oom-killer kills a process on ChromeOS.
59   TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM,
60 #endif
61 #if BUILDFLAG(IS_ANDROID)
62   // On Android processes are spawned from the system Zygote and we do not get
63   // the termination status.  We can't know if the termination was a crash or an
64   // oom kill for sure, but we can use status of the strong process bindings as
65   // a hint.
66   TERMINATION_STATUS_OOM_PROTECTED,        // child was protected from oom kill
67 #endif
68   TERMINATION_STATUS_LAUNCH_FAILED,        // child process never launched
69   TERMINATION_STATUS_OOM,                  // Process died due to oom
70 #if BUILDFLAG(IS_WIN)
71   // On Windows, the OS terminated process due to code integrity failure.
72   TERMINATION_STATUS_INTEGRITY_FAILURE,
73 #endif
74   TERMINATION_STATUS_MAX_ENUM
75   // clang-format on
76 };
77 
78 // Attempts to kill all the processes on the current machine that were launched
79 // from the given executable name, ending them with the given exit code.  If
80 // filter is non-null, then only processes selected by the filter are killed.
81 // Returns true if all processes were able to be killed off, false if at least
82 // one couldn't be killed.
83 BASE_EXPORT bool KillProcesses(const FilePath::StringType& executable_name,
84                                int exit_code,
85                                const ProcessFilter* filter);
86 
87 // Get the termination status of the process by interpreting the
88 // circumstances of the child process' death. |exit_code| is set to
89 // the status returned by waitpid() on POSIX, and from GetExitCodeProcess() on
90 // Windows, and may not be null.  Note that on Linux, this function
91 // will only return a useful result the first time it is called after
92 // the child exits (because it will reap the child and the information
93 // will no longer be available).
94 BASE_EXPORT TerminationStatus GetTerminationStatus(ProcessHandle handle,
95                                                    int* exit_code);
96 
97 #if BUILDFLAG(IS_POSIX)
98 // Send a kill signal to the process and then wait for the process to exit
99 // and get the termination status.
100 //
101 // This is used in situations where it is believed that the process is dead
102 // or dying (because communication with the child process has been cut).
103 // In order to avoid erroneously returning that the process is still running
104 // because the kernel is still cleaning it up, this will wait for the process
105 // to terminate. In order to avoid the risk of hanging while waiting for the
106 // process to terminate, send a SIGKILL to the process before waiting for the
107 // termination status.
108 //
109 // Note that it is not an option to call WaitForExitCode and then
110 // GetTerminationStatus as the child will be reaped when WaitForExitCode
111 // returns, and this information will be lost.
112 //
113 BASE_EXPORT TerminationStatus GetKnownDeadTerminationStatus(
114     ProcessHandle handle, int* exit_code);
115 
116 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
117 // Spawns a thread to wait asynchronously for the child |process| to exit
118 // and then reaps it.
119 BASE_EXPORT void EnsureProcessGetsReaped(Process process);
120 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
121 #endif  // BUILDFLAG(IS_POSIX)
122 
123 // Registers |process| to be asynchronously monitored for termination, forcibly
124 // terminated if necessary, and reaped on exit. The caller should have signalled
125 // |process| to exit before calling this API. The API will allow a couple of
126 // seconds grace period before forcibly terminating |process|.
127 // TODO(https://crbug.com/806451): The Mac implementation currently blocks the
128 // calling thread for up to two seconds.
129 BASE_EXPORT void EnsureProcessTerminated(Process process);
130 
131 // These are only sparingly used, and not needed on Fuchsia. They could be
132 // implemented if necessary.
133 #if !BUILDFLAG(IS_FUCHSIA)
134 // Wait for all the processes based on the named executable to exit.  If filter
135 // is non-null, then only processes selected by the filter are waited on.
136 // Returns after all processes have exited or wait_milliseconds have expired.
137 // Returns true if all the processes exited, false otherwise.
138 BASE_EXPORT bool WaitForProcessesToExit(
139     const FilePath::StringType& executable_name,
140     base::TimeDelta wait,
141     const ProcessFilter* filter);
142 
143 // Waits a certain amount of time (can be 0) for all the processes with a given
144 // executable name to exit, then kills off any of them that are still around.
145 // If filter is non-null, then only processes selected by the filter are waited
146 // on.  Killed processes are ended with the given exit code.  Returns false if
147 // any processes needed to be killed, true if they all exited cleanly within
148 // the wait_milliseconds delay.
149 BASE_EXPORT bool CleanupProcesses(const FilePath::StringType& executable_name,
150                                   base::TimeDelta wait,
151                                   int exit_code,
152                                   const ProcessFilter* filter);
153 #endif  // !BUILDFLAG(IS_FUCHSIA)
154 
155 }  // namespace base
156 
157 #endif  // BASE_PROCESS_KILL_H_
158