Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [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 | |
| 5 | // This file contains functions for launching subprocesses. |
| 6 | |
| 7 | #ifndef BASE_PROCESS_LAUNCH_H_ |
| 8 | #define BASE_PROCESS_LAUNCH_H_ |
| 9 | |
Devon Loehr | 8a1b40c | 2024-09-09 14:52:41 | [diff] [blame] | 10 | #include <limits.h> |
avi | beced7c | 2015-12-24 06:47:59 | [diff] [blame] | 11 | #include <stddef.h> |
| 12 | |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 13 | #include <string> |
Helmut Januschka | bfa62f7 | 2024-04-04 15:18:31 | [diff] [blame] | 14 | #include <string_view> |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 15 | #include <utility> |
| 16 | #include <vector> |
| 17 | |
| 18 | #include "base/base_export.h" |
Jan Wilken Dörrie | 6bdce49 | 2019-11-05 11:36:50 | [diff] [blame] | 19 | #include "base/command_line.h" |
[email protected] | b345c48 | 2013-08-30 18:00:39 | [diff] [blame] | 20 | #include "base/environment.h" |
Lei Zhang | 1757508 | 2021-05-10 20:19:18 | [diff] [blame] | 21 | #include "base/files/file_path.h" |
S. Ganesh | 4e21a58a | 2025-04-15 17:13:34 | [diff] [blame] | 22 | #include "base/functional/function_ref.h" |
Wez | 4e86105 | 2023-07-12 12:18:57 | [diff] [blame] | 23 | #include "base/memory/raw_ptr.h" |
rvargas | 6293e5b | 2014-12-01 22:53:09 | [diff] [blame] | 24 | #include "base/process/process.h" |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 25 | #include "base/process/process_handle.h" |
Gabriel Charette | 6836c0d5 | 2021-01-11 17:40:26 | [diff] [blame] | 26 | #include "base/threading/thread_restrictions.h" |
S. Ganesh | 4e21a58a | 2025-04-15 17:13:34 | [diff] [blame] | 27 | #include "base/time/time.h" |
Dave Tapuska | 6cd5272 | 2023-03-06 20:25:29 | [diff] [blame] | 28 | #include "build/blink_buildflags.h" |
avi | beced7c | 2015-12-24 06:47:59 | [diff] [blame] | 29 | #include "build/build_config.h" |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 30 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 31 | #if BUILDFLAG(IS_WIN) |
Bruce Dawson | 9df510e | 2021-07-14 15:23:08 | [diff] [blame] | 32 | #include "base/win/windows_types.h" |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 33 | #elif BUILDFLAG(IS_FUCHSIA) |
Wez | 5c3c6f15 | 2018-06-09 18:24:02 | [diff] [blame] | 34 | #include <lib/fdio/spawn.h> |
Scott Graham | fe0e9f46 | 2017-09-18 21:25:04 | [diff] [blame] | 35 | #include <zircon/types.h> |
scottmg | e5a1d49 | 2017-05-24 23:41:43 | [diff] [blame] | 36 | #endif |
| 37 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 38 | #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
Fabrice de Gans-Riberi | 306871de | 2018-05-16 19:38:39 | [diff] [blame] | 39 | #include "base/posix/file_descriptor_shuffle.h" |
| 40 | #endif |
| 41 | |
Ken Rockot | 3eb1d12e | 2024-06-12 04:18:35 | [diff] [blame] | 42 | #if BUILDFLAG(IS_ANDROID) |
| 43 | #include "base/android/binder.h" |
| 44 | #endif |
| 45 | |
Mark Rowe | 5862e12 | 2024-10-14 17:35:01 | [diff] [blame] | 46 | #if BUILDFLAG(IS_MAC) |
| 47 | #include "base/mac/process_requirement.h" |
| 48 | #endif |
| 49 | |
[email protected] | 285bc48 | 2023-03-02 22:35:36 | [diff] [blame] | 50 | namespace base { |
| 51 | |
S. Ganesh | 4e21a58a | 2025-04-15 17:13:34 | [diff] [blame] | 52 | enum TerminationStatus : int; |
| 53 | |
Devon Loehr | 8a1b40c | 2024-09-09 14:52:41 | [diff] [blame] | 54 | #if BUILDFLAG(IS_POSIX) |
| 55 | // Some code (e.g. the sandbox) relies on PTHREAD_STACK_MIN |
| 56 | // being async-signal-safe, which is no longer guaranteed by POSIX |
| 57 | // (it may call sysconf, which is not safe). |
| 58 | // To work around this, use a hardcoded value unless it's already |
| 59 | // defined as a constant. |
| 60 | |
S. Ganesh | 4e21a58a | 2025-04-15 17:13:34 | [diff] [blame] | 61 | // These constants are borrowed from glibc's (arch)/bits/pthread_stack_min.h. |
Wang Qing | 87ae6c7 | 2025-03-20 23:20:44 | [diff] [blame] | 62 | #if defined(ARCH_CPU_ARM64) || defined(ARCH_CPU_LOONGARCH64) |
Devon Loehr | 8a1b40c | 2024-09-09 14:52:41 | [diff] [blame] | 63 | #define PTHREAD_STACK_MIN_CONST \ |
| 64 | (__builtin_constant_p(PTHREAD_STACK_MIN) ? PTHREAD_STACK_MIN : 131072) |
| 65 | #else |
| 66 | #define PTHREAD_STACK_MIN_CONST \ |
| 67 | (__builtin_constant_p(PTHREAD_STACK_MIN) ? PTHREAD_STACK_MIN : 16384) |
| 68 | #endif // defined(ARCH_CPU_ARM64) |
| 69 | |
| 70 | static_assert(__builtin_constant_p(PTHREAD_STACK_MIN_CONST), |
| 71 | "must be constant"); |
| 72 | |
| 73 | // Make sure our hardcoded value is large enough to accommodate the |
| 74 | // actual minimum stack size. This function will run a one-time CHECK |
| 75 | // and so should be called at some point, preferably during startup. |
| 76 | BASE_EXPORT void CheckPThreadStackMinIsSafe(); |
| 77 | #endif // BUILDFLAG(IS_POSIX) |
| 78 | |
Gyuyoung Kim | 40cc667c | 2025-04-15 14:07:26 | [diff] [blame] | 79 | #if BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_IOS_TVOS) |
Dave Tapuska | 6cd5272 | 2023-03-06 20:25:29 | [diff] [blame] | 80 | class MachRendezvousPort; |
| 81 | using MachPortsForRendezvous = std::map<uint32_t, MachRendezvousPort>; |
| 82 | #endif |
| 83 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 84 | #if BUILDFLAG(IS_WIN) |
[email protected] | 991bd8a | 2013-12-12 18:45:45 | [diff] [blame] | 85 | typedef std::vector<HANDLE> HandlesToInheritVector; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 86 | #elif BUILDFLAG(IS_FUCHSIA) |
Kevin Marshall | ad910ae2 | 2018-06-16 05:40:53 | [diff] [blame] | 87 | struct PathToTransfer { |
| 88 | base::FilePath path; |
| 89 | zx_handle_t handle; |
| 90 | }; |
Wez | 1603c32 | 2017-08-10 05:24:54 | [diff] [blame] | 91 | struct HandleToTransfer { |
| 92 | uint32_t id; |
Scott Graham | fe0e9f46 | 2017-09-18 21:25:04 | [diff] [blame] | 93 | zx_handle_t handle; |
Wez | 1603c32 | 2017-08-10 05:24:54 | [diff] [blame] | 94 | }; |
| 95 | typedef std::vector<HandleToTransfer> HandlesToTransferVector; |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 96 | typedef std::vector<std::pair<int, int>> FileHandleMappingVector; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 97 | #elif BUILDFLAG(IS_POSIX) |
Fabrice de Gans-Riberi | 306871de | 2018-05-16 19:38:39 | [diff] [blame] | 98 | typedef std::vector<std::pair<int, int>> FileHandleMappingVector; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 99 | #endif // BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 100 | |
| 101 | // Options for launching a subprocess that are passed to LaunchProcess(). |
| 102 | // The default constructor constructs the object with default options. |
[email protected] | b345c48 | 2013-08-30 18:00:39 | [diff] [blame] | 103 | struct BASE_EXPORT LaunchOptions { |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 104 | #if (BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)) && !BUILDFLAG(IS_APPLE) |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 105 | // Delegate to be run in between fork and exec in the subprocess (see |
| 106 | // pre_exec_delegate below) |
| 107 | class BASE_EXPORT PreExecDelegate { |
| 108 | public: |
Chris Watkins | 091d629 | 2017-12-13 04:25:58 | [diff] [blame] | 109 | PreExecDelegate() = default; |
Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 110 | |
| 111 | PreExecDelegate(const PreExecDelegate&) = delete; |
| 112 | PreExecDelegate& operator=(const PreExecDelegate&) = delete; |
| 113 | |
Chris Watkins | 091d629 | 2017-12-13 04:25:58 | [diff] [blame] | 114 | virtual ~PreExecDelegate() = default; |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 115 | |
| 116 | // Since this is to be run between fork and exec, and fork may have happened |
| 117 | // while multiple threads were running, this function needs to be async |
| 118 | // safe. |
| 119 | virtual void RunAsyncSafe() = 0; |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 120 | }; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 121 | #endif // BUILDFLAG(IS_POSIX) |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 122 | |
[email protected] | b345c48 | 2013-08-30 18:00:39 | [diff] [blame] | 123 | LaunchOptions(); |
vmpstr | 7c787706 | 2016-02-18 22:12:24 | [diff] [blame] | 124 | LaunchOptions(const LaunchOptions&); |
[email protected] | b345c48 | 2013-08-30 18:00:39 | [diff] [blame] | 125 | ~LaunchOptions(); |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 126 | |
| 127 | // If true, wait for the process to complete. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 128 | bool wait = false; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 129 | |
sergeyu | 78205516 | 2016-04-06 08:57:59 | [diff] [blame] | 130 | // If not empty, change to this directory before executing the new process. |
| 131 | base::FilePath current_directory; |
| 132 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 133 | #if BUILDFLAG(IS_WIN) |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 134 | bool start_hidden = false; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 135 | |
Joe Mason | cae7d8a | 2022-03-25 00:10:02 | [diff] [blame] | 136 | // Process will be started using ShellExecuteEx instead of CreateProcess so |
| 137 | // that it is elevated. LaunchProcess with this flag will have different |
| 138 | // behaviour due to ShellExecuteEx. Some common operations like OpenProcess |
| 139 | // will fail. Currently the only other supported LaunchOptions are |
| 140 | // |start_hidden| and |wait|. |
Alex Gough | b245386 | 2022-01-11 19:29:28 | [diff] [blame] | 141 | bool elevated = false; |
| 142 | |
S. Ganesh | c18d593 | 2018-11-05 03:45:31 | [diff] [blame] | 143 | // Sets STARTF_FORCEOFFFEEDBACK so that the feedback cursor is forced off |
| 144 | // while the process is starting. |
| 145 | bool feedback_cursor_off = false; |
| 146 | |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 147 | // Windows can inherit handles when it launches child processes. |
| 148 | // See https://blogs.msdn.microsoft.com/oldnewthing/20111216-00/?p=8873 |
| 149 | // for a good overview of Windows handle inheritance. |
| 150 | // |
| 151 | // Implementation note: it might be nice to implement in terms of |
Arthur Sonzogni | e5fff99c | 2024-02-21 15:58:24 | [diff] [blame] | 152 | // std::optional<>, but then the natural default state (vector not present) |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 153 | // would be "all inheritable handles" while we want "no inheritance." |
| 154 | enum class Inherit { |
| 155 | // Only those handles in |handles_to_inherit| vector are inherited. If the |
| 156 | // vector is empty, no handles are inherited. The handles in the vector must |
| 157 | // all be inheritable. |
| 158 | kSpecific, |
[email protected] | 991bd8a | 2013-12-12 18:45:45 | [diff] [blame] | 159 | |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 160 | // All handles in the current process which are inheritable are inherited. |
| 161 | // In production code this flag should be used only when running |
| 162 | // short-lived, trusted binaries, because open handles from other libraries |
| 163 | // and subsystems will leak to the child process, causing errors such as |
| 164 | // open socket hangs. There are also race conditions that can cause handle |
| 165 | // over-sharing. |
| 166 | // |
| 167 | // |handles_to_inherit| must be null. |
| 168 | // |
| 169 | // DEPRECATED. THIS SHOULD NOT BE USED. Explicitly map all handles that |
| 170 | // need to be shared in new code. |
| 171 | // TODO(brettw) bug 748258: remove this. |
| 172 | kAll |
| 173 | }; |
| 174 | Inherit inherit_mode = Inherit::kSpecific; |
| 175 | HandlesToInheritVector handles_to_inherit; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 176 | |
[email protected] | 991bd8a | 2013-12-12 18:45:45 | [diff] [blame] | 177 | // If non-null, runs as if the user represented by the token had launched it. |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 178 | // Whether the application is visible on the interactive desktop depends on |
| 179 | // the token belonging to an interactive logon session. |
| 180 | // |
| 181 | // To avoid hard to diagnose problems, when specified this loads the |
| 182 | // environment variables associated with the user and if this operation fails |
| 183 | // the entire call fails as well. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 184 | UserTokenHandle as_user = nullptr; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 185 | |
| 186 | // If true, use an empty string for the desktop name. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 187 | bool empty_desktop_name = false; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 188 | |
[email protected] | 991bd8a | 2013-12-12 18:45:45 | [diff] [blame] | 189 | // If non-null, launches the application in that job object. The process will |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 190 | // be terminated immediately and LaunchProcess() will fail if assignment to |
| 191 | // the job object fails. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 192 | HANDLE job_handle = nullptr; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 193 | |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 194 | // Handles for the redirection of stdin, stdout and stderr. The caller should |
| 195 | // either set all three of them or none (i.e. there is no way to redirect |
| 196 | // stderr without redirecting stdin). |
| 197 | // |
| 198 | // The handles must be inheritable. Pseudo handles are used when stdout and |
| 199 | // stderr redirect to the console. In that case, GetFileType() will return |
| 200 | // FILE_TYPE_CHAR and they're automatically inherited by child processes. See |
| 201 | // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682075.aspx |
| 202 | // Otherwise, the caller must ensure that the |inherit_mode| and/or |
| 203 | // |handles_to_inherit| set so that the handles are inherited. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 204 | HANDLE stdin_handle = nullptr; |
| 205 | HANDLE stdout_handle = nullptr; |
| 206 | HANDLE stderr_handle = nullptr; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 207 | |
| 208 | // If set to true, ensures that the child process is launched with the |
| 209 | // CREATE_BREAKAWAY_FROM_JOB flag which allows it to breakout of the parent |
| 210 | // job if any. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 211 | bool force_breakaway_from_job_ = false; |
Greg Thompson | 47faf20 | 2018-05-18 20:59:03 | [diff] [blame] | 212 | |
| 213 | // If set to true, permission to bring windows to the foreground is passed to |
| 214 | // the launched process if the current process has such permission. |
| 215 | bool grant_foreground_privilege = false; |
Alex Gough | d383c77 | 2021-02-17 04:39:34 | [diff] [blame] | 216 | |
| 217 | // If set to true, sets a process mitigation flag to disable Hardware-enforced |
| 218 | // Stack Protection for the process. |
| 219 | // This overrides /cetcompat if set on the executable. See: |
| 220 | // https://docs.microsoft.com/en-us/cpp/build/reference/cetcompat?view=msvc-160 |
| 221 | // If not supported by Windows, has no effect. This flag weakens security by |
| 222 | // turning off ROP protection. |
| 223 | bool disable_cetcompat = false; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 224 | #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 225 | // Remap file descriptors according to the mapping of src_fd->dest_fd to |
| 226 | // propagate FDs into the child process. |
| 227 | FileHandleMappingVector fds_to_remap; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 228 | #endif // BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 229 | |
Ken Rockot | 3eb1d12e | 2024-06-12 04:18:35 | [diff] [blame] | 230 | #if BUILDFLAG(IS_ANDROID) |
| 231 | // Set of strong IBinder references to be passed to the child process. These |
| 232 | // make their way to ChildProcessServiceDelegate.onConnectionSetup (Java) |
| 233 | // within the new child process. |
| 234 | std::vector<android::BinderRef> binders; |
| 235 | #endif |
| 236 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 237 | #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
David Benjamin | 76ee79eb | 2019-03-15 17:02:09 | [diff] [blame] | 238 | // Set/unset environment variables. These are applied on top of the parent |
| 239 | // process environment. Empty (the default) means to inherit the same |
| 240 | // environment. See internal::AlterEnvironment(). |
| 241 | EnvironmentMap environment; |
| 242 | |
| 243 | // Clear the environment for the new process before processing changes from |
| 244 | // |environment|. |
| 245 | bool clear_environment = false; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 246 | #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
David Benjamin | 76ee79eb | 2019-03-15 17:02:09 | [diff] [blame] | 247 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 248 | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 249 | // If non-zero, start the process using clone(), using flags as provided. |
rickyz | f1eb9cc | 2015-01-13 22:59:48 | [diff] [blame] | 250 | // Unlike in clone, clone_flags may not contain a custom termination signal |
| 251 | // that is sent to the parent when the child dies. The termination signal will |
| 252 | // always be set to SIGCHLD. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 253 | int clone_flags = 0; |
[email protected] | d078691 | 2014-04-09 20:06:26 | [diff] [blame] | 254 | |
| 255 | // By default, child processes will have the PR_SET_NO_NEW_PRIVS bit set. If |
| 256 | // true, then this bit will not be set in the new child process. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 257 | bool allow_new_privs = false; |
phajdan.jr | ed5ed8f4 | 2015-03-13 21:40:13 | [diff] [blame] | 258 | |
| 259 | // Sets parent process death signal to SIGKILL. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 260 | bool kill_on_parent_death = false; |
Peter Varga | bfba107 | 2023-11-08 21:30:11 | [diff] [blame] | 261 | |
| 262 | // File descriptors of the parent process with FD_CLOEXEC flag to be removed |
| 263 | // before calling exec*(). |
| 264 | std::vector<int> fds_to_remove_cloexec; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 265 | #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 266 | |
Dave Tapuska | 6cd5272 | 2023-03-06 20:25:29 | [diff] [blame] | 267 | #if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK)) |
Gyuyoung Kim | 40cc667c | 2025-04-15 14:07:26 | [diff] [blame] | 268 | #if !BUILDFLAG(IS_IOS_TVOS) |
Robert Sesek | a6d5986 | 2019-03-05 16:06:47 | [diff] [blame] | 269 | // Mach ports that will be accessible to the child process. These are not |
| 270 | // directly inherited across process creation, but they are stored by a Mach |
| 271 | // IPC server that a child process can communicate with to retrieve them. |
| 272 | // |
| 273 | // After calling LaunchProcess(), any rights that were transferred with MOVE |
| 274 | // dispositions will be consumed, even on failure. |
| 275 | // |
Mark Rowe | ced178d | 2024-10-08 21:16:09 | [diff] [blame] | 276 | // See base/apple/mach_port_rendezvous.h for details. |
Robert Sesek | a6d5986 | 2019-03-05 16:06:47 | [diff] [blame] | 277 | MachPortsForRendezvous mach_ports_for_rendezvous; |
Gyuyoung Kim | 40cc667c | 2025-04-15 14:07:26 | [diff] [blame] | 278 | #endif // !BUILDFLAG(IS_IOS_TVOS) |
Robert Sesek | 34025cb9 | 2019-08-22 00:07:53 | [diff] [blame] | 279 | |
Dave Tapuska | ed322d0 | 2023-03-07 23:33:33 | [diff] [blame] | 280 | // Apply a process scheduler policy to enable mitigations against CPU side- |
| 281 | // channel attacks. |
| 282 | bool enable_cpu_security_mitigations = false; |
| 283 | #endif // BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK)) |
| 284 | |
| 285 | #if BUILDFLAG(IS_MAC) |
Robert Sesek | 34025cb9 | 2019-08-22 00:07:53 | [diff] [blame] | 286 | // When a child process is launched, the system tracks the parent process |
| 287 | // with a concept of "responsibility". The responsible process will be |
| 288 | // associated with any requests for private data stored on the system via |
| 289 | // the TCC subsystem. When launching processes that run foreign/third-party |
| 290 | // code, the responsibility for the child process should be disclaimed so |
| 291 | // that any TCC requests are not associated with the parent. |
| 292 | bool disclaim_responsibility = false; |
Mark Rowe | 5862e12 | 2024-10-14 17:35:01 | [diff] [blame] | 293 | |
| 294 | // A `ProcessRequirement` that will be used to validate the launched process |
| 295 | // before it can retrieve `mach_ports_for_rendezvous`. |
| 296 | std::optional<mac::ProcessRequirement> process_requirement; |
| 297 | #endif // BUILDFLAG(IS_MAC) |
Robert Sesek | a6d5986 | 2019-03-05 16:06:47 | [diff] [blame] | 298 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 299 | #if BUILDFLAG(IS_FUCHSIA) |
scottmg | e5a1d49 | 2017-05-24 23:41:43 | [diff] [blame] | 300 | // If valid, launches the application in that job object. |
Scott Graham | fe0e9f46 | 2017-09-18 21:25:04 | [diff] [blame] | 301 | zx_handle_t job_handle = ZX_HANDLE_INVALID; |
Wez | 1603c32 | 2017-08-10 05:24:54 | [diff] [blame] | 302 | |
| 303 | // Specifies additional handles to transfer (not duplicate) to the child |
Wez | 0629d40 | 2018-06-06 00:26:43 | [diff] [blame] | 304 | // process. Each entry is an <id,handle> pair, with an |id| created using the |
Kevin Marshall | 40dc4360 | 2018-06-16 01:33:55 | [diff] [blame] | 305 | // PA_HND() macro. The child retrieves the handle |
| 306 | // |zx_take_startup_handle(id)|. The supplied handles are consumed by |
| 307 | // LaunchProcess() even on failure. |
Wez | 35e50b5 | 2018-12-01 01:52:44 | [diff] [blame] | 308 | // Note that PA_USER1 ids are reserved for use by AddHandleToTransfer(), below |
| 309 | // and by convention PA_USER0 is reserved for use by the embedding |
| 310 | // application. |
Wez | 1603c32 | 2017-08-10 05:24:54 | [diff] [blame] | 311 | HandlesToTransferVector handles_to_transfer; |
Kevin Marshall | 65c2670 | 2017-09-25 18:21:42 | [diff] [blame] | 312 | |
Wez | 35e50b5 | 2018-12-01 01:52:44 | [diff] [blame] | 313 | // Allocates a unique id for |handle| in |handles_to_transfer|, inserts it, |
| 314 | // and returns the generated id. |
| 315 | static uint32_t AddHandleToTransfer( |
| 316 | HandlesToTransferVector* handles_to_transfer, |
| 317 | zx_handle_t handle); |
| 318 | |
Wez | 0629d40 | 2018-06-06 00:26:43 | [diff] [blame] | 319 | // Specifies which basic capabilities to grant to the child process. |
| 320 | // By default the child process will receive the caller's complete namespace, |
Fabrice de Gans-Riberi | 930bbf4b | 2021-02-04 23:18:56 | [diff] [blame] | 321 | // access to the current base::GetDefaultJob(), handles for stdio and access |
| 322 | // to the dynamic library loader. |
Wez | 0629d40 | 2018-06-06 00:26:43 | [diff] [blame] | 323 | // Note that the child is always provided access to the loader service. |
| 324 | uint32_t spawn_flags = FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_STDIO | |
| 325 | FDIO_SPAWN_CLONE_JOB; |
Kevin Marshall | 2bd0455 | 2018-02-01 21:23:45 | [diff] [blame] | 326 | |
Wez | 0629d40 | 2018-06-06 00:26:43 | [diff] [blame] | 327 | // Specifies paths to clone from the calling process' namespace into that of |
Kevin Marshall | ad910ae2 | 2018-06-16 05:40:53 | [diff] [blame] | 328 | // the child process. If |paths_to_clone| is empty then the process will |
| 329 | // receive either a full copy of the parent's namespace, or an empty one, |
| 330 | // depending on whether FDIO_SPAWN_CLONE_NAMESPACE is set. |
Wez | 821a3b8 | 2023-04-04 17:55:32 | [diff] [blame] | 331 | // Process launch will fail if `paths_to_clone` and `paths_to_transfer` |
| 332 | // together contain conflicting paths (e.g. overlaps or duplicates). |
Wez | 4e86105 | 2023-07-12 12:18:57 | [diff] [blame] | 333 | std::vector<FilePath> paths_to_clone; |
Kevin Marshall | ad910ae2 | 2018-06-16 05:40:53 | [diff] [blame] | 334 | |
| 335 | // Specifies handles which will be installed as files or directories in the |
Wez | 821a3b8 | 2023-04-04 17:55:32 | [diff] [blame] | 336 | // child process' namespace. |
| 337 | // Process launch will fail if `paths_to_clone` and `paths_to_transfer` |
| 338 | // together contain conflicting paths (e.g. overlaps or duplicates). |
Kevin Marshall | ad910ae2 | 2018-06-16 05:40:53 | [diff] [blame] | 339 | std::vector<PathToTransfer> paths_to_transfer; |
Sergey Ulanov | 53ab7dd | 2019-08-27 17:53:18 | [diff] [blame] | 340 | |
| 341 | // Suffix that will be added to the process name. When specified process name |
| 342 | // will be set to "<binary_name><process_suffix>". |
| 343 | std::string process_name_suffix; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 344 | #endif // BUILDFLAG(IS_FUCHSIA) |
scottmg | e5a1d49 | 2017-05-24 23:41:43 | [diff] [blame] | 345 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 346 | #if BUILDFLAG(IS_POSIX) |
rkjnsn | 732f03d | 2016-10-03 17:59:54 | [diff] [blame] | 347 | // If not empty, launch the specified executable instead of |
| 348 | // cmdline.GetProgram(). This is useful when it is necessary to pass a custom |
| 349 | // argv[0]. |
| 350 | base::FilePath real_path; |
| 351 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 352 | #if !BUILDFLAG(IS_APPLE) |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 353 | // If non-null, a delegate to be run immediately prior to executing the new |
| 354 | // program in the child process. |
| 355 | // |
| 356 | // WARNING: If LaunchProcess is called in the presence of multiple threads, |
| 357 | // code running in this delegate essentially needs to be async-signal safe |
| 358 | // (see man 7 signal for a list of allowed functions). |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 359 | raw_ptr<PreExecDelegate> pre_exec_delegate = nullptr; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 360 | #endif // !BUILDFLAG(IS_APPLE) |
Wez | dc9eb2b12 | 2018-01-09 04:43:07 | [diff] [blame] | 361 | |
| 362 | // Each element is an RLIMIT_* constant that should be raised to its |
| 363 | // rlim_max. This pointer is owned by the caller and must live through |
| 364 | // the call to LaunchProcess(). |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 365 | raw_ptr<const std::vector<int>> maximize_rlimits = nullptr; |
Wez | dc9eb2b12 | 2018-01-09 04:43:07 | [diff] [blame] | 366 | |
| 367 | // If true, start the process in a new process group, instead of |
| 368 | // inheriting the parent's process group. The pgid of the child process |
| 369 | // will be the same as its pid. |
| 370 | bool new_process_group = false; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 371 | #endif // BUILDFLAG(IS_POSIX) |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 372 | |
Eric Willigers | 611cf54 | 2022-04-28 02:22:14 | [diff] [blame] | 373 | #if BUILDFLAG(IS_CHROMEOS) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 374 | // If non-negative, the specified file descriptor will be set as the launched |
| 375 | // process' controlling terminal. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 376 | int ctrl_terminal_fd = -1; |
Eric Willigers | 611cf54 | 2022-04-28 02:22:14 | [diff] [blame] | 377 | #endif // BUILDFLAG(IS_CHROMEOS) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 378 | }; |
| 379 | |
| 380 | // Launch a process via the command line |cmdline|. |
| 381 | // See the documentation of LaunchOptions for details on |options|. |
| 382 | // |
rvargas | c40cfc6 | 2014-12-02 02:46:36 | [diff] [blame] | 383 | // Returns a valid Process upon success. |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 384 | // |
| 385 | // Unix-specific notes: |
| 386 | // - All file descriptors open in the parent process will be closed in the |
| 387 | // child process except for any preserved by options::fds_to_remap, and |
| 388 | // stdin, stdout, and stderr. If not remapped by options::fds_to_remap, |
| 389 | // stdin is reopened as /dev/null, and the child is allowed to inherit its |
| 390 | // parent's stdout and stderr. |
| 391 | // - If the first argument on the command line does not contain a slash, |
| 392 | // PATH will be searched. (See man execvp.) |
rvargas | c40cfc6 | 2014-12-02 02:46:36 | [diff] [blame] | 393 | BASE_EXPORT Process LaunchProcess(const CommandLine& cmdline, |
| 394 | const LaunchOptions& options); |
| 395 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 396 | #if BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 397 | // Windows-specific LaunchProcess that takes the command line as a |
| 398 | // string. Useful for situations where you need to control the |
| 399 | // command line arguments directly, but prefer the CommandLine version |
Joe Mason | cae7d8a | 2022-03-25 00:10:02 | [diff] [blame] | 400 | // if launching Chrome itself. Also prefer the CommandLine version if |
| 401 | // `options.elevated` is set because `cmdline` needs to be parsed for |
| 402 | // ShellExecuteEx. |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 403 | // |
| 404 | // The first command line argument should be the path to the process, |
| 405 | // and don't forget to quote it. |
| 406 | // |
| 407 | // Example (including literal quotes) |
| 408 | // cmdline = "c:\windows\explorer.exe" -foo "c:\bar\" |
Jan Wilken Dörrie | 6bdce49 | 2019-11-05 11:36:50 | [diff] [blame] | 409 | BASE_EXPORT Process LaunchProcess(const CommandLine::StringType& cmdline, |
rvargas | 6181277 | 2014-12-05 03:14:54 | [diff] [blame] | 410 | const LaunchOptions& options); |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 411 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 412 | #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 413 | // A POSIX-specific version of LaunchProcess that takes an argv array |
| 414 | // instead of a CommandLine. Useful for situations where you need to |
| 415 | // control the command line arguments directly, but prefer the |
| 416 | // CommandLine version if launching Chrome itself. |
rvargas | 02a9986 | 2015-01-10 00:46:12 | [diff] [blame] | 417 | BASE_EXPORT Process LaunchProcess(const std::vector<std::string>& argv, |
| 418 | const LaunchOptions& options); |
| 419 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 420 | #if !BUILDFLAG(IS_APPLE) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 421 | // Close all file descriptors, except those which are a destination in the |
| 422 | // given multimap. Only call this function in a child process where you know |
| 423 | // that there aren't any other threads. |
| 424 | BASE_EXPORT void CloseSuperfluousFds(const InjectiveMultimap& saved_map); |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 425 | #endif // BUILDFLAG(IS_APPLE) |
| 426 | #endif // BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 427 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 428 | #if BUILDFLAG(IS_WIN) |
[email protected] | 15db082 | 2013-09-13 21:24:47 | [diff] [blame] | 429 | // Set |job_object|'s JOBOBJECT_EXTENDED_LIMIT_INFORMATION |
| 430 | // BasicLimitInformation.LimitFlags to |limit_flags|. |
| 431 | BASE_EXPORT bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags); |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 432 | |
| 433 | // Output multi-process printf, cout, cerr, etc to the cmd.exe console that ran |
| 434 | // chrome. This is not thread-safe: only call from main thread. |
jam | 79dc59a | 2015-08-17 03:38:16 | [diff] [blame] | 435 | BASE_EXPORT void RouteStdioToConsole(bool create_console_if_not_found); |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 436 | #endif // BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 437 | |
| 438 | // Executes the application specified by |cl| and wait for it to exit. Stores |
| 439 | // the output (stdout) in |output|. Redirects stderr to /dev/null. Returns true |
| 440 | // on success (application launched and exited cleanly, with exit code |
| 441 | // indicating success). |
| 442 | BASE_EXPORT bool GetAppOutput(const CommandLine& cl, std::string* output); |
| 443 | |
jam | 79dc59a | 2015-08-17 03:38:16 | [diff] [blame] | 444 | // Like GetAppOutput, but also includes stderr. |
| 445 | BASE_EXPORT bool GetAppOutputAndError(const CommandLine& cl, |
| 446 | std::string* output); |
| 447 | |
Zijie He | e9d42a3 | 2017-07-17 20:37:55 | [diff] [blame] | 448 | // A version of |GetAppOutput()| which also returns the exit code of the |
| 449 | // executed command. Returns true if the application runs and exits cleanly. If |
| 450 | // this is the case the exit code of the application is available in |
| 451 | // |*exit_code|. |
| 452 | BASE_EXPORT bool GetAppOutputWithExitCode(const CommandLine& cl, |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 453 | std::string* output, |
| 454 | int* exit_code); |
Zijie He | e9d42a3 | 2017-07-17 20:37:55 | [diff] [blame] | 455 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 456 | #if BUILDFLAG(IS_WIN) |
[email protected] | 7eb6bec6 | 2013-12-05 22:41:04 | [diff] [blame] | 457 | // A Windows-specific version of GetAppOutput that takes a command line string |
| 458 | // instead of a CommandLine object. Useful for situations where you need to |
| 459 | // control the command line arguments directly. |
Lei Zhang | bbaae12 | 2024-07-31 21:01:24 | [diff] [blame] | 460 | BASE_EXPORT bool GetAppOutput(CommandLine::StringViewType cl, |
Jan Wilken Dörrie | 6bdce49 | 2019-11-05 11:36:50 | [diff] [blame] | 461 | std::string* output); |
S. Ganesh | 4e21a58a | 2025-04-15 17:13:34 | [diff] [blame] | 462 | |
| 463 | // A Windows-specific version of `GetAppOutput` that allows the ability to |
| 464 | // specify: |
| 465 | // * an optional `output` providing the complete output of `cl`. |
| 466 | // * an optional `timeout` if `cl` does not complete in time. |
S. Ganesh | 77e6d46 | 2025-04-17 18:03:47 | [diff] [blame] | 467 | // * an optional `LaunchOptions`. |
S. Ganesh | 4e21a58a | 2025-04-15 17:13:34 | [diff] [blame] | 468 | // * an optional `FunctionRef`, called multiple times while waiting, with |
| 469 | // streaming partial output received since the last call to the `FunctionRef` |
| 470 | // from stdout/stderr of the running `cl` process. The implementation of the |
| 471 | // `FunctionRef` can log the output, or concatenate the partial outputs over |
| 472 | // successive calls to effectively produce the full `output` from the `cl` |
| 473 | // process. |
| 474 | // * an optional `final_status` `TerminationStatus` value on function return. |
S. Ganesh | ebce36d | 2025-05-21 03:58:39 | [diff] [blame] | 475 | // |
| 476 | // Returns `true` if the application runs and exits. If this is the case the |
| 477 | // exit code of the application is available in `*exit_code`, and `final_status` |
| 478 | // will be `TERMINATION_STATUS_NORMAL_TERMINATION`. |
| 479 | // |
| 480 | // Returns `false` under the following conditions: |
| 481 | // * If the application does not exist, `final_status` will be |
| 482 | // `TERMINATION_STATUS_LAUNCH_FAILED`. |
| 483 | // * If the application does not terminate within `timeout`, `final_status` will |
| 484 | // be `TERMINATION_STATUS_STILL_RUNNING`. |
| 485 | // |
S. Ganesh | 4e21a58a | 2025-04-15 17:13:34 | [diff] [blame] | 486 | // Note that the expected use cases for this function do not expect `cl` to |
| 487 | // produce a lot of output. This function will not work optimally with lots of |
| 488 | // output from the `cl` process, since it waits a second each time between |
| 489 | // reading the output. |
| 490 | BASE_EXPORT bool GetAppOutputWithExitCodeAndTimeout( |
S. Ganesh | 77e6d46 | 2025-04-17 18:03:47 | [diff] [blame] | 491 | CommandLine::StringViewType cl, |
S. Ganesh | 4e21a58a | 2025-04-15 17:13:34 | [diff] [blame] | 492 | bool include_stderr, |
| 493 | std::string* output, |
| 494 | int* exit_code, |
| 495 | TimeDelta timeout = TimeDelta::Max(), |
S. Ganesh | 77e6d46 | 2025-04-17 18:03:47 | [diff] [blame] | 496 | const LaunchOptions& options = {}, |
S. Ganesh | 4e21a58a | 2025-04-15 17:13:34 | [diff] [blame] | 497 | FunctionRef<void(std::string_view)> still_waiting = |
| 498 | [](std::string_view partial_output) {}, |
| 499 | TerminationStatus* final_status = nullptr); |
| 500 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 501 | #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 502 | // A POSIX-specific version of GetAppOutput that takes an argv array |
| 503 | // instead of a CommandLine. Useful for situations where you need to |
| 504 | // control the command line arguments directly. |
| 505 | BASE_EXPORT bool GetAppOutput(const std::vector<std::string>& argv, |
| 506 | std::string* output); |
| 507 | |
jbudorick | 86c756c | 2017-03-29 17:33:54 | [diff] [blame] | 508 | // Like the above POSIX-specific version of GetAppOutput, but also includes |
| 509 | // stderr. |
| 510 | BASE_EXPORT bool GetAppOutputAndError(const std::vector<std::string>& argv, |
| 511 | std::string* output); |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 512 | #endif // BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 513 | |
| 514 | // If supported on the platform, and the user has sufficent rights, increase |
| 515 | // the current process's scheduling priority to a high priority. |
| 516 | BASE_EXPORT void RaiseProcessToHighPriority(); |
| 517 | |
[email protected] | d078691 | 2014-04-09 20:06:26 | [diff] [blame] | 518 | // Creates a LaunchOptions object suitable for launching processes in a test |
| 519 | // binary. This should not be called in production/released code. |
| 520 | BASE_EXPORT LaunchOptions LaunchOptionsForTest(); |
| 521 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 522 | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) |
rickyz | a2f6d74 | 2015-01-21 21:57:34 | [diff] [blame] | 523 | // A wrapper for clone with fork-like behavior, meaning that it returns the |
| 524 | // child's pid in the parent and 0 in the child. |flags|, |ptid|, and |ctid| are |
| 525 | // as in the clone system call (the CLONE_VM flag is not supported). |
| 526 | // |
| 527 | // This function uses the libc clone wrapper (which updates libc's pid cache) |
| 528 | // internally, so callers may expect things like getpid() to work correctly |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 529 | // after in both the child and parent. |
rickyz | a2f6d74 | 2015-01-21 21:57:34 | [diff] [blame] | 530 | // |
| 531 | // As with fork(), callers should be extremely careful when calling this while |
| 532 | // multiple threads are running, since at the time the fork happened, the |
| 533 | // threads could have been in any state (potentially holding locks, etc.). |
| 534 | // Callers should most likely call execve() in the child soon after calling |
| 535 | // this. |
Tom Anderson | 24df4195 | 2017-07-25 02:41:01 | [diff] [blame] | 536 | // |
| 537 | // It is unsafe to use any pthread APIs after ForkWithFlags(). |
| 538 | // However, performing an exec() will lift this restriction. |
Peter Kasting | 25acd594 | 2022-07-07 17:45:15 | [diff] [blame] | 539 | BASE_EXPORT pid_t ForkWithFlags(int flags, pid_t* ptid, pid_t* ctid); |
rickyz | a2f6d74 | 2015-01-21 21:57:34 | [diff] [blame] | 540 | #endif |
| 541 | |
Gabriel Charette | 6836c0d5 | 2021-01-11 17:40:26 | [diff] [blame] | 542 | namespace internal { |
| 543 | |
| 544 | // Friend and derived class of ScopedAllowBaseSyncPrimitives which allows |
| 545 | // GetAppOutputInternal() to join a process. GetAppOutputInternal() can't itself |
| 546 | // be a friend of ScopedAllowBaseSyncPrimitives because it is in the anonymous |
| 547 | // namespace. |
Peter Kasting | 89a70ae3 | 2023-03-09 02:15:39 | [diff] [blame] | 548 | class [[maybe_unused, nodiscard]] GetAppOutputScopedAllowBaseSyncPrimitives |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 549 | : public base::ScopedAllowBaseSyncPrimitives {}; |
Gabriel Charette | 6836c0d5 | 2021-01-11 17:40:26 | [diff] [blame] | 550 | |
| 551 | } // namespace internal |
| 552 | |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 553 | } // namespace base |
| 554 | |
| 555 | #endif // BASE_PROCESS_LAUNCH_H_ |