Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2011 The Chromium Authors |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
danakj | 0a44860 | 2015-03-10 00:31:16 | [diff] [blame] | 5 | #ifndef BASE_PROCESS_PROCESS_H_ |
| 6 | #define BASE_PROCESS_PROCESS_H_ |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 7 | |
Helmut Januschka | bfa62f7 | 2024-04-04 15:18:31 | [diff] [blame] | 8 | #include <string_view> |
| 9 | |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 10 | #include "base/base_export.h" |
Tom Sepez | 1705e3f0 | 2024-10-25 01:39:18 | [diff] [blame] | 11 | #include "base/compiler_specific.h" |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 12 | #include "base/process/process_handle.h" |
rvargas | 126fd582 | 2014-12-12 00:25:14 | [diff] [blame] | 13 | #include "base/time/time.h" |
Dave Tapuska | ed322d0 | 2023-03-07 23:33:33 | [diff] [blame] | 14 | #include "build/blink_buildflags.h" |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 15 | #include "build/build_config.h" |
| 16 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 17 | #if BUILDFLAG(IS_WIN) |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 18 | #include "base/win/scoped_handle.h" |
| 19 | #endif |
| 20 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 21 | #if BUILDFLAG(IS_FUCHSIA) |
Wez | 157707d6 | 2018-07-10 22:48:47 | [diff] [blame] | 22 | #include <lib/zx/process.h> |
Wez | 78b73313 | 2017-08-09 18:41:59 | [diff] [blame] | 23 | #endif |
| 24 | |
Zheda Chen | 2808be7 | 2022-12-19 06:26:55 | [diff] [blame] | 25 | #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) |
lgrey | 0d2bafc | 2016-11-07 16:28:33 | [diff] [blame] | 26 | #include "base/feature_list.h" |
Zheda Chen | 2808be7 | 2022-12-19 06:26:55 | [diff] [blame] | 27 | #endif // BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 28 | |
| 29 | #if BUILDFLAG(IS_APPLE) |
lgrey | 0d2bafc | 2016-11-07 16:28:33 | [diff] [blame] | 30 | #include "base/process/port_provider_mac.h" |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 31 | #endif // BUILDFLAG(IS_APPLE) |
lgrey | 0d2bafc | 2016-11-07 16:28:33 | [diff] [blame] | 32 | |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 33 | namespace base { |
| 34 | |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 35 | #if BUILDFLAG(IS_CHROMEOS) |
| 36 | // OneGroupPerRenderer feature places each foreground renderer process into |
| 37 | // its own cgroup. This will cause the scheduler to use the aggregate runtime |
| 38 | // of all threads in the process when deciding on the next thread to schedule. |
| 39 | // It will help guarantee fairness between renderers. |
Daniel Cheng | 0fff5c23 | 2022-09-21 17:43:34 | [diff] [blame] | 40 | BASE_EXPORT BASE_DECLARE_FEATURE(kOneGroupPerRenderer); |
Joel Fernandes | f3f294f | 2023-09-22 17:29:45 | [diff] [blame] | 41 | |
| 42 | // Set all threads of a background process as backgrounded, which changes the |
| 43 | // thread attributes including c-group, latency sensitivity. But the nice value |
| 44 | // is unchanged, since background process is under the spell of the background |
| 45 | // CPU c-group (via cgroup.procs). |
| 46 | BASE_EXPORT BASE_DECLARE_FEATURE(kSetThreadBgForBgProcess); |
Shintaro Kawamura | f29c8fdf | 2024-03-28 03:40:08 | [diff] [blame] | 47 | |
Shintaro Kawamura | db0ae3e | 2024-12-26 07:41:33 | [diff] [blame] | 48 | // FlattenCpuCgroups feature uses /sys/fs/cgroup/cpu/chrome_renderers and |
| 49 | // /sys/fs/cgroup/cpu/chrome_renderers_background cpu cgroups for renderer |
| 50 | // processes instead of nested cpu cgroups. Nested cpu cgroups has an overhead |
| 51 | // on task scheduling. |
| 52 | BASE_EXPORT BASE_DECLARE_FEATURE(kFlattenCpuCgroups); |
| 53 | |
Shintaro Kawamura | f29c8fdf | 2024-03-28 03:40:08 | [diff] [blame] | 54 | class ProcessPriorityDelegate; |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 55 | #endif |
| 56 | |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 57 | // Provides a move-only encapsulation of a process. |
| 58 | // |
| 59 | // This object is not tied to the lifetime of the underlying process: the |
| 60 | // process may be killed and this object may still around, and it will still |
| 61 | // claim to be valid. The actual behavior in that case is OS dependent like so: |
| 62 | // |
| 63 | // Windows: The underlying ProcessHandle will be valid after the process dies |
| 64 | // and can be used to gather some information about that process, but most |
| 65 | // methods will obviously fail. |
| 66 | // |
Wez | 6fcf59f | 2017-08-02 21:09:05 | [diff] [blame] | 67 | // POSIX: The underlying ProcessHandle is not guaranteed to remain valid after |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 68 | // the process dies, and it may be reused by the system, which means that it may |
| 69 | // end up pointing to the wrong process. |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 70 | class BASE_EXPORT Process { |
| 71 | public: |
erikchen | 7cef7d26 | 2017-09-11 22:56:57 | [diff] [blame] | 72 | // On Windows, this takes ownership of |handle|. On POSIX, this does not take |
| 73 | // ownership of |handle|. |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 74 | explicit Process(ProcessHandle handle = kNullProcessHandle); |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 75 | |
dcheng | e1b0277c | 2015-12-01 12:09:52 | [diff] [blame] | 76 | Process(Process&& other); |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 77 | |
Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 78 | Process(const Process&) = delete; |
| 79 | Process& operator=(const Process&) = delete; |
| 80 | |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 81 | // The destructor does not terminate the process. |
thakis | 3096dac | 2015-04-20 16:44:48 | [diff] [blame] | 82 | ~Process(); |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 83 | |
dcheng | e1b0277c | 2015-12-01 12:09:52 | [diff] [blame] | 84 | Process& operator=(Process&& other); |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 85 | |
| 86 | // Returns an object for the current process. |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 87 | static Process Current(); |
| 88 | |
rvargas | 6b039c37 | 2015-02-04 21:11:29 | [diff] [blame] | 89 | // Returns a Process for the given |pid|. |
| 90 | static Process Open(ProcessId pid); |
| 91 | |
rvargas | 747ff24 | 2015-01-17 02:46:47 | [diff] [blame] | 92 | // Returns a Process for the given |pid|. On Windows the handle is opened |
| 93 | // with more access rights and must only be used by trusted code (can read the |
| 94 | // address space and duplicate handles). |
rvargas | 1c376a8 | 2015-03-16 23:03:52 | [diff] [blame] | 95 | static Process OpenWithExtraPrivileges(ProcessId pid); |
rvargas | 747ff24 | 2015-01-17 02:46:47 | [diff] [blame] | 96 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 97 | #if BUILDFLAG(IS_WIN) |
rvargas | 17a407d | 2015-01-23 20:36:44 | [diff] [blame] | 98 | // Returns a Process for the given |pid|, using some |desired_access|. |
| 99 | // See ::OpenProcess documentation for valid |desired_access|. |
| 100 | static Process OpenWithAccess(ProcessId pid, DWORD desired_access); |
| 101 | #endif |
| 102 | |
Patrick Monette | 5d1ba7ca | 2023-08-02 22:05:27 | [diff] [blame] | 103 | // Returns true if changing the priority of processes through `SetPriority()` |
| 104 | // is possible. |
| 105 | static bool CanSetPriority(); |
| 106 | |
haraken | 940efb9 | 2017-02-08 05:58:15 | [diff] [blame] | 107 | // Terminates the current process immediately with |exit_code|. |
Wez | 5f11741 | 2018-02-07 04:17:47 | [diff] [blame] | 108 | [[noreturn]] static void TerminateCurrentProcessImmediately(int exit_code); |
haraken | 940efb9 | 2017-02-08 05:58:15 | [diff] [blame] | 109 | |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 110 | // Returns true if this objects represents a valid process. |
| 111 | bool IsValid() const; |
| 112 | |
| 113 | // Returns a handle for this process. There is no guarantee about when that |
| 114 | // handle becomes invalid because this object retains ownership. |
| 115 | ProcessHandle Handle() const; |
| 116 | |
| 117 | // Returns a second object that represents this process. |
| 118 | Process Duplicate() const; |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 119 | |
Robert Sesek | 0e7f165a | 2020-11-20 21:31:45 | [diff] [blame] | 120 | // Relinquishes ownership of the handle and sets this to kNullProcessHandle. |
| 121 | // The result may be a pseudo-handle, depending on the OS and value stored in |
| 122 | // this. |
Daniel Cheng | 4455c984 | 2022-01-13 23:26:37 | [diff] [blame] | 123 | [[nodiscard]] ProcessHandle Release(); |
Robert Sesek | 0e7f165a | 2020-11-20 21:31:45 | [diff] [blame] | 124 | |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 125 | // Get the PID for this process. |
rvargas | 960db88 | 2015-01-24 00:27:25 | [diff] [blame] | 126 | ProcessId Pid() const; |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 127 | |
Francois Doray | 7d131534 | 2018-10-21 03:54:47 | [diff] [blame] | 128 | // Get the creation time for this process. Since the Pid can be reused after a |
| 129 | // process dies, it is useful to use both the Pid and the creation time to |
| 130 | // uniquely identify a process. |
| 131 | // |
Benoit Lize | 8a54469 | 2020-08-31 15:43:42 | [diff] [blame] | 132 | // On Android, works only if |this| is the current process, as security |
| 133 | // features prevent an application from getting data about other processes, |
| 134 | // even if they belong to us. Otherwise, returns Time(). |
Francois Doray | 7d131534 | 2018-10-21 03:54:47 | [diff] [blame] | 135 | Time CreationTime() const; |
Francois Doray | 7d131534 | 2018-10-21 03:54:47 | [diff] [blame] | 136 | |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 137 | // Returns true if this process is the current process. |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 138 | bool is_current() const; |
| 139 | |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 140 | #if BUILDFLAG(IS_CHROMEOS) |
| 141 | // A unique token generated for each process, this is used to create a unique |
| 142 | // cgroup for each renderer. |
Tom Sepez | 1705e3f0 | 2024-10-25 01:39:18 | [diff] [blame] | 143 | const std::string& unique_token() const LIFETIME_BOUND { |
| 144 | return unique_token_; |
| 145 | } |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 146 | #endif |
| 147 | |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 148 | // Close the process handle. This will not terminate the process. |
| 149 | void Close(); |
| 150 | |
Zijie He | 4dd88ae42 | 2017-09-20 01:30:18 | [diff] [blame] | 151 | // Returns true if this process is still running. This is only safe on Windows |
| 152 | // (and maybe Fuchsia?), because the ProcessHandle will keep the zombie |
| 153 | // process information available until itself has been released. But on Posix, |
| 154 | // the OS may reuse the ProcessId. |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 155 | #if BUILDFLAG(IS_WIN) |
Zijie He | 4dd88ae42 | 2017-09-20 01:30:18 | [diff] [blame] | 156 | bool IsRunning() const { |
| 157 | return !WaitForExitWithTimeout(base::TimeDelta(), nullptr); |
| 158 | } |
| 159 | #endif |
| 160 | |
rvargas | 02ad783 | 2015-04-02 01:36:06 | [diff] [blame] | 161 | // Terminates the process with extreme prejudice. The given |exit_code| will |
rvargas | eedb763 | 2015-03-09 23:53:45 | [diff] [blame] | 162 | // be the exit code of the process. If |wait| is true, this method will wait |
| 163 | // for up to one minute for the process to actually terminate. |
| 164 | // Returns true if the process terminates within the allowed time. |
Johann | 30f9447 | 2021-04-07 23:54:24 | [diff] [blame] | 165 | // NOTE: |exit_code| is only used on OS_WIN. |
rvargas | 02ad783 | 2015-04-02 01:36:06 | [diff] [blame] | 166 | bool Terminate(int exit_code, bool wait) const; |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 167 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 168 | #if BUILDFLAG(IS_WIN) |
Mike Rorke | f36971b | 2020-03-06 17:56:29 | [diff] [blame] | 169 | enum class WaitExitStatus { |
| 170 | PROCESS_EXITED, |
| 171 | STOP_EVENT_SIGNALED, |
| 172 | FAILED, |
| 173 | }; |
| 174 | |
| 175 | // Waits for the process to exit, or the specified |stop_event_handle| to be |
| 176 | // set. Returns value indicating which event was set. The given |exit_code| |
| 177 | // will be the exit code of the process. |
| 178 | WaitExitStatus WaitForExitOrEvent( |
| 179 | const base::win::ScopedHandle& stop_event_handle, |
| 180 | int* exit_code) const; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 181 | #endif // BUILDFLAG(IS_WIN) |
Mike Rorke | f36971b | 2020-03-06 17:56:29 | [diff] [blame] | 182 | |
rvargas | 126fd582 | 2014-12-12 00:25:14 | [diff] [blame] | 183 | // Waits for the process to exit. Returns true on success. |
| 184 | // On POSIX, if the process has been signaled then |exit_code| is set to -1. |
rvargas | 2f70a15 | 2015-02-24 00:28:11 | [diff] [blame] | 185 | // On Linux this must be a child process, however on Mac and Windows it can be |
| 186 | // any process. |
g.mehndiratt | fd19e23 | 2015-05-29 08:17:14 | [diff] [blame] | 187 | // NOTE: |exit_code| is optional, nullptr can be passed if the exit code is |
| 188 | // not required. |
jcivelli | f4462a35 | 2017-01-10 04:45:59 | [diff] [blame] | 189 | bool WaitForExit(int* exit_code) const; |
rvargas | 126fd582 | 2014-12-12 00:25:14 | [diff] [blame] | 190 | |
| 191 | // Same as WaitForExit() but only waits for up to |timeout|. |
g.mehndiratt | fd19e23 | 2015-05-29 08:17:14 | [diff] [blame] | 192 | // NOTE: |exit_code| is optional, nullptr can be passed if the exit code |
| 193 | // is not required. |
jcivelli | f4462a35 | 2017-01-10 04:45:59 | [diff] [blame] | 194 | bool WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) const; |
rvargas | 126fd582 | 2014-12-12 00:25:14 | [diff] [blame] | 195 | |
Brian White | ae2a8b9a | 2017-11-02 19:10:36 | [diff] [blame] | 196 | // Indicates that the process has exited with the specified |exit_code|. |
| 197 | // This should be called if process exit is observed outside of this class. |
| 198 | // (i.e. Not because Terminate or WaitForExit, above, was called.) |
| 199 | // Note that nothing prevents this being called multiple times for a dead |
| 200 | // process though that should be avoided. |
| 201 | void Exited(int exit_code) const; |
| 202 | |
Patrick Monette | 5d1ba7ca | 2023-08-02 22:05:27 | [diff] [blame] | 203 | // The different priorities that a process can have. |
| 204 | // TODO(pmonette): Consider merging with base::TaskPriority when the API is |
| 205 | // stable. |
| 206 | enum class Priority { |
| 207 | // The process does not contribute to content that is currently important |
| 208 | // to the user. Lowest priority. |
| 209 | kBestEffort, |
| 210 | |
Zheda Chen | e7421f3 | 2024-08-29 03:05:39 | [diff] [blame] | 211 | // The process contributes to content that is visible to the user, but the |
| 212 | // work don't have significant performance or latency requirement, so it can |
| 213 | // run in energy efficient manner. Moderate priority. |
Patrick Monette | 5d1ba7ca | 2023-08-02 22:05:27 | [diff] [blame] | 214 | kUserVisible, |
| 215 | |
| 216 | // The process contributes to content that is of the utmost importance to |
| 217 | // the user, like producing audible content, or visible content in the |
Zheda Chen | e7421f3 | 2024-08-29 03:05:39 | [diff] [blame] | 218 | // main frame. High priority. |
Patrick Monette | 5d1ba7ca | 2023-08-02 22:05:27 | [diff] [blame] | 219 | kUserBlocking, |
Patrick Monette | 617db89 | 2024-09-24 17:29:19 | [diff] [blame] | 220 | |
| 221 | kMaxValue = kUserBlocking, |
Patrick Monette | 5d1ba7ca | 2023-08-02 22:05:27 | [diff] [blame] | 222 | }; |
| 223 | |
Gyuyoung Kim | 9e4c3ef | 2025-02-12 01:17:57 | [diff] [blame] | 224 | #if (BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK))) && \ |
Raphael Kubo da Costa | c57d2df3 | 2025-03-01 00:51:43 | [diff] [blame] | 225 | !BUILDFLAG(IS_IOS_TVOS) |
lgrey | 0d2bafc | 2016-11-07 16:28:33 | [diff] [blame] | 226 | // The Mac needs a Mach port in order to manipulate a process's priority, |
| 227 | // and there's no good way to get that from base given the pid. These Mac |
Patrick Monette | 5d1ba7ca | 2023-08-02 22:05:27 | [diff] [blame] | 228 | // variants of the `GetPriority()` and `SetPriority()` API take a port |
| 229 | // provider for this reason. See crbug.com/460102. |
lgrey | 0d2bafc | 2016-11-07 16:28:33 | [diff] [blame] | 230 | |
Patrick Monette | 5d1ba7ca | 2023-08-02 22:05:27 | [diff] [blame] | 231 | // Retrieves the priority of the process. Defaults to Priority::kUserBlocking |
| 232 | // if the priority could not be retrieved, or if `port_provider` is null. |
| 233 | Priority GetPriority(PortProvider* port_provider) const; |
| 234 | |
| 235 | // Sets the priority of the process process. Returns true if the priority was |
| 236 | // changed, false otherwise. If `port_provider` is null, this is a no-op and |
| 237 | // it returns false. |
| 238 | bool SetPriority(PortProvider* port_provider, Priority priority); |
lgrey | 0d2bafc | 2016-11-07 16:28:33 | [diff] [blame] | 239 | #else |
Patrick Monette | 5d1ba7ca | 2023-08-02 22:05:27 | [diff] [blame] | 240 | // Retrieves the priority of the process. Defaults to Priority::kUserBlocking |
| 241 | // if the priority could not be retrieved. |
| 242 | Priority GetPriority() const; |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 243 | |
Patrick Monette | 5d1ba7ca | 2023-08-02 22:05:27 | [diff] [blame] | 244 | // Sets the priority of the process process. Returns true if the priority was |
| 245 | // changed, false otherwise. |
| 246 | bool SetPriority(Priority priority); |
Dave Tapuska | ed322d0 | 2023-03-07 23:33:33 | [diff] [blame] | 247 | #endif // BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK)) |
| 248 | |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 249 | // Returns an integer representing the priority of a process. The meaning |
| 250 | // of this value is OS dependent. |
Patrick Monette | 740b81b | 2023-07-21 21:09:09 | [diff] [blame] | 251 | int GetOSPriority() const; |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 252 | |
Georg Neis | ff37fb5 | 2025-02-05 09:05:26 | [diff] [blame] | 253 | #if BUILDFLAG(IS_CHROMEOS) |
nya | d2c548b | 2015-12-09 03:22:32 | [diff] [blame] | 254 | // Get the PID in its PID namespace. |
| 255 | // If the process is not in a PID namespace or /proc/<pid>/status does not |
| 256 | // report NSpid, kNullProcessId is returned. |
| 257 | ProcessId GetPidInNamespace() const; |
| 258 | #endif |
| 259 | |
Matthew Denton | f96988342 | 2023-08-08 01:44:34 | [diff] [blame] | 260 | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) |
| 261 | // Returns true if the process has any seccomp policy applied. |
| 262 | bool IsSeccompSandboxed(); |
| 263 | #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) |
| 264 | |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 265 | #if BUILDFLAG(IS_CHROMEOS) |
Shintaro Kawamura | f29c8fdf | 2024-03-28 03:40:08 | [diff] [blame] | 266 | // Sets a delegate which handles process priority changes. This |
| 267 | // must be externally synchronized with any call to base::Process methods. |
| 268 | static void SetProcessPriorityDelegate(ProcessPriorityDelegate* delegate); |
| 269 | |
Youssef Esmat | 10aa75d | 2022-06-10 11:58:46 | [diff] [blame] | 270 | // Exposes OneGroupPerRendererEnabled() to unit tests. |
| 271 | static bool OneGroupPerRendererEnabledForTesting(); |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 272 | |
| 273 | // If OneGroupPerRenderer is enabled, runs at process startup to clean up |
| 274 | // any stale cgroups that were left behind from any unclean exits of the |
| 275 | // browser process. |
| 276 | static void CleanUpStaleProcessStates(); |
| 277 | |
Shintaro Kawamura | f726c129 | 2024-03-28 03:40:08 | [diff] [blame] | 278 | // Initializes the process's priority. |
| 279 | // |
| 280 | // This should be called before SetPriority(). |
| 281 | // |
| 282 | // If SchedQoSOnResourcedForChrome is enabled, this creates a cache entry for |
| 283 | // the process priority. The returned `base::Process::PriorityEntry` should be |
| 284 | // freed when the process is terminated so that the cached entry is freed from |
| 285 | // the internal map. |
| 286 | // |
| 287 | // If OneGroupPerRenderer is enabled, it also creates a unique cgroup for the |
| 288 | // process. |
| 289 | // This is a no-op if the Process is not valid or if it has already been |
| 290 | // called. |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 291 | void InitializePriority(); |
Shintaro Kawamura | f726c129 | 2024-03-28 03:40:08 | [diff] [blame] | 292 | |
| 293 | // Clears the entities initialized by InitializePriority(). |
| 294 | // |
| 295 | // This is no-op if SchedQoSOnResourcedForChrome is disabled. |
| 296 | void ForgetPriority(); |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 297 | #endif // BUILDFLAG(IS_CHROMEOS) |
| 298 | |
Dave Tapuska | ed322d0 | 2023-03-07 23:33:33 | [diff] [blame] | 299 | #if BUILDFLAG(IS_APPLE) |
Patrick Monette | 209f31da | 2023-08-31 21:25:33 | [diff] [blame] | 300 | // Sets the priority of the current process to its default value. |
Gabriel Charette | 99c4dc96 | 2025-01-06 20:54:38 | [diff] [blame] | 301 | // Ironically, non-App Nap compliant processes do not get this by default on |
| 302 | // Mac. |
Patrick Monette | ee7f72f | 2023-01-23 22:59:45 | [diff] [blame] | 303 | static void SetCurrentTaskDefaultRole(); |
| 304 | #endif // BUILDFLAG(IS_MAC) |
| 305 | |
Dave Tapuska | 31c385c | 2024-04-12 18:43:11 | [diff] [blame] | 306 | #if BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK) |
Dave Tapuska | b742233 | 2025-05-22 22:10:39 | [diff] [blame] | 307 | using TerminateCallback = bool (*)(ProcessHandle handle, |
| 308 | int exit_code, |
| 309 | bool wait); |
Dave Tapuska | 31c385c | 2024-04-12 18:43:11 | [diff] [blame] | 310 | using WaitForExitCallback = bool (*)(ProcessHandle handle, |
| 311 | int* exit_code, |
| 312 | base::TimeDelta timeout); |
| 313 | // Function ptrs to implement termination without polluting //base with |
| 314 | // BrowserEngineKit APIs. |
| 315 | static void SetTerminationHooks(TerminateCallback terminate_callback, |
| 316 | WaitForExitCallback wait_callback); |
| 317 | #if TARGET_OS_SIMULATOR |
| 318 | // Methods for supporting both "content processes" and traditional |
| 319 | // forked processes. For non-simulator builds on iOS every process would |
| 320 | // be a "content process" so we don't need the conditionals. |
| 321 | void SetIsContentProcess(); |
| 322 | bool IsContentProcess() const; |
| 323 | #endif |
| 324 | #endif |
| 325 | |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 326 | private: |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 327 | #if BUILDFLAG(IS_CHROMEOS) |
| 328 | // Cleans up process state. If OneGroupPerRenderer is enabled, it cleans up |
| 329 | // the cgroup created by InitializePriority(). If the process has not |
| 330 | // fully terminated yet, it will post a background task to try again. |
| 331 | void CleanUpProcess(int remaining_retries) const; |
| 332 | |
| 333 | // Calls CleanUpProcess() on a background thread. |
| 334 | void CleanUpProcessAsync() const; |
| 335 | |
| 336 | // Used to call CleanUpProcess() on a background thread because Process is not |
| 337 | // refcounted. |
| 338 | static void CleanUpProcessScheduled(Process process, int remaining_retries); |
| 339 | #endif // BUILDFLAG(IS_CHROMEOS) |
| 340 | |
Dave Tapuska | 31c385c | 2024-04-12 18:43:11 | [diff] [blame] | 341 | #if !BUILDFLAG(IS_IOS) || (BUILDFLAG(IS_IOS) && TARGET_OS_SIMULATOR) |
| 342 | bool TerminateInternal(int exit_code, bool wait) const; |
| 343 | bool WaitForExitWithTimeoutImpl(base::ProcessHandle handle, |
| 344 | int* exit_code, |
| 345 | base::TimeDelta timeout) const; |
| 346 | #endif |
| 347 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 348 | #if BUILDFLAG(IS_WIN) |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 349 | win::ScopedHandle process_; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 350 | #elif BUILDFLAG(IS_FUCHSIA) |
Wez | 157707d6 | 2018-07-10 22:48:47 | [diff] [blame] | 351 | zx::process process_; |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 352 | #else |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 353 | ProcessHandle process_; |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 354 | #endif |
dcheng | 1a2fd6cd | 2016-06-07 21:39:12 | [diff] [blame] | 355 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 356 | #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_FUCHSIA) |
scottmg | 297cc93 | 2017-05-24 03:45:58 | [diff] [blame] | 357 | bool is_current_process_; |
| 358 | #endif |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 359 | |
Dave Tapuska | 31c385c | 2024-04-12 18:43:11 | [diff] [blame] | 360 | #if BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK) && TARGET_OS_SIMULATOR |
| 361 | // A flag indicating that this is a "content process". iOS does not support |
| 362 | // generic process invocation but it does support some types of well defined |
| 363 | // processes. These types of processes are defined at the //content layer so |
| 364 | // for termination we defer to some globally initialized callbacks. |
| 365 | bool content_process_ = false; |
| 366 | #endif |
| 367 | |
Youssef Esmat | c732bf8 | 2022-05-27 00:47:19 | [diff] [blame] | 368 | #if BUILDFLAG(IS_CHROMEOS) |
| 369 | // A unique token per process not per class instance (`base::Process`). This |
| 370 | // is similar to the PID of a process but should not be reused after the |
| 371 | // process's termination. The token will be copied during Duplicate() |
| 372 | // and move semantics as is the PID/ProcessHandle. |
| 373 | std::string unique_token_; |
| 374 | #endif |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 375 | }; |
| 376 | |
Eric Willigers | 611cf54 | 2022-04-28 02:22:14 | [diff] [blame] | 377 | #if BUILDFLAG(IS_CHROMEOS) |
afakhry | 8b4796b | 2015-11-16 18:41:44 | [diff] [blame] | 378 | // Exposed for testing. |
| 379 | // Given the contents of the /proc/<pid>/cgroup file, determine whether the |
| 380 | // process is backgrounded or not. |
Patrick Monette | 5d1ba7ca | 2023-08-02 22:05:27 | [diff] [blame] | 381 | BASE_EXPORT Process::Priority GetProcessPriorityCGroup( |
Helmut Januschka | bfa62f7 | 2024-04-04 15:18:31 | [diff] [blame] | 382 | std::string_view cgroup_contents); |
Eric Willigers | 611cf54 | 2022-04-28 02:22:14 | [diff] [blame] | 383 | #endif // BUILDFLAG(IS_CHROMEOS) |
afakhry | 8b4796b | 2015-11-16 18:41:44 | [diff] [blame] | 384 | |
[email protected] | 76bea67 | 2013-07-19 16:48:56 | [diff] [blame] | 385 | } // namespace base |
| 386 | |
danakj | 0a44860 | 2015-03-10 00:31:16 | [diff] [blame] | 387 | #endif // BASE_PROCESS_PROCESS_H_ |