xref: /aosp_15_r20/external/cronet/base/process/launch_mac.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 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/launch.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <crt_externs.h>
8*6777b538SAndroid Build Coastguard Worker #include <mach/mach.h>
9*6777b538SAndroid Build Coastguard Worker #include <os/availability.h>
10*6777b538SAndroid Build Coastguard Worker #include <spawn.h>
11*6777b538SAndroid Build Coastguard Worker #include <string.h>
12*6777b538SAndroid Build Coastguard Worker #include <sys/wait.h>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/files/scoped_file.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/mac/mach_port_rendezvous.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/posix/eintr_wrapper.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/process/environment_internal.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker extern "C" {
26*6777b538SAndroid Build Coastguard Worker // Changes the current thread's directory to a path or directory file
27*6777b538SAndroid Build Coastguard Worker // descriptor.
28*6777b538SAndroid Build Coastguard Worker int pthread_chdir_np(const char* dir);
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker int pthread_fchdir_np(int fd);
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker int responsibility_spawnattrs_setdisclaim(posix_spawnattr_t attrs,
33*6777b538SAndroid Build Coastguard Worker                                           int disclaim);
34*6777b538SAndroid Build Coastguard Worker }  // extern "C"
35*6777b538SAndroid Build Coastguard Worker 
36*6777b538SAndroid Build Coastguard Worker namespace base {
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker namespace {
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker // DPSXCHECK is a Debug Posix Spawn Check macro. The posix_spawn* family of
41*6777b538SAndroid Build Coastguard Worker // functions return an errno value, as opposed to setting errno directly. This
42*6777b538SAndroid Build Coastguard Worker // macro emulates a DPCHECK().
43*6777b538SAndroid Build Coastguard Worker #define DPSXCHECK(expr)                                              \
44*6777b538SAndroid Build Coastguard Worker   do {                                                               \
45*6777b538SAndroid Build Coastguard Worker     int rv = (expr);                                                 \
46*6777b538SAndroid Build Coastguard Worker     DCHECK_EQ(rv, 0) << #expr << ": -" << rv << " " << strerror(rv); \
47*6777b538SAndroid Build Coastguard Worker   } while (0)
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker class PosixSpawnAttr {
50*6777b538SAndroid Build Coastguard Worker  public:
PosixSpawnAttr()51*6777b538SAndroid Build Coastguard Worker   PosixSpawnAttr() { DPSXCHECK(posix_spawnattr_init(&attr_)); }
52*6777b538SAndroid Build Coastguard Worker 
~PosixSpawnAttr()53*6777b538SAndroid Build Coastguard Worker   ~PosixSpawnAttr() { DPSXCHECK(posix_spawnattr_destroy(&attr_)); }
54*6777b538SAndroid Build Coastguard Worker 
get()55*6777b538SAndroid Build Coastguard Worker   posix_spawnattr_t* get() { return &attr_; }
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker  private:
58*6777b538SAndroid Build Coastguard Worker   posix_spawnattr_t attr_;
59*6777b538SAndroid Build Coastguard Worker };
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker class PosixSpawnFileActions {
62*6777b538SAndroid Build Coastguard Worker  public:
PosixSpawnFileActions()63*6777b538SAndroid Build Coastguard Worker   PosixSpawnFileActions() {
64*6777b538SAndroid Build Coastguard Worker     DPSXCHECK(posix_spawn_file_actions_init(&file_actions_));
65*6777b538SAndroid Build Coastguard Worker   }
66*6777b538SAndroid Build Coastguard Worker 
67*6777b538SAndroid Build Coastguard Worker   PosixSpawnFileActions(const PosixSpawnFileActions&) = delete;
68*6777b538SAndroid Build Coastguard Worker   PosixSpawnFileActions& operator=(const PosixSpawnFileActions&) = delete;
69*6777b538SAndroid Build Coastguard Worker 
~PosixSpawnFileActions()70*6777b538SAndroid Build Coastguard Worker   ~PosixSpawnFileActions() {
71*6777b538SAndroid Build Coastguard Worker     DPSXCHECK(posix_spawn_file_actions_destroy(&file_actions_));
72*6777b538SAndroid Build Coastguard Worker   }
73*6777b538SAndroid Build Coastguard Worker 
Open(int filedes,const char * path,int mode)74*6777b538SAndroid Build Coastguard Worker   void Open(int filedes, const char* path, int mode) {
75*6777b538SAndroid Build Coastguard Worker     DPSXCHECK(posix_spawn_file_actions_addopen(&file_actions_, filedes, path,
76*6777b538SAndroid Build Coastguard Worker                                                mode, 0));
77*6777b538SAndroid Build Coastguard Worker   }
78*6777b538SAndroid Build Coastguard Worker 
Dup2(int filedes,int newfiledes)79*6777b538SAndroid Build Coastguard Worker   void Dup2(int filedes, int newfiledes) {
80*6777b538SAndroid Build Coastguard Worker     DPSXCHECK(
81*6777b538SAndroid Build Coastguard Worker         posix_spawn_file_actions_adddup2(&file_actions_, filedes, newfiledes));
82*6777b538SAndroid Build Coastguard Worker   }
83*6777b538SAndroid Build Coastguard Worker 
Inherit(int filedes)84*6777b538SAndroid Build Coastguard Worker   void Inherit(int filedes) {
85*6777b538SAndroid Build Coastguard Worker     DPSXCHECK(posix_spawn_file_actions_addinherit_np(&file_actions_, filedes));
86*6777b538SAndroid Build Coastguard Worker   }
87*6777b538SAndroid Build Coastguard Worker 
88*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_MAC)
Chdir(const char * path)89*6777b538SAndroid Build Coastguard Worker   void Chdir(const char* path) {
90*6777b538SAndroid Build Coastguard Worker     DPSXCHECK(posix_spawn_file_actions_addchdir_np(&file_actions_, path));
91*6777b538SAndroid Build Coastguard Worker   }
92*6777b538SAndroid Build Coastguard Worker #endif
93*6777b538SAndroid Build Coastguard Worker 
get() const94*6777b538SAndroid Build Coastguard Worker   const posix_spawn_file_actions_t* get() const { return &file_actions_; }
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker  private:
97*6777b538SAndroid Build Coastguard Worker   posix_spawn_file_actions_t file_actions_;
98*6777b538SAndroid Build Coastguard Worker };
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_MAC)
ChangeCurrentThreadDirectory(const char * path)101*6777b538SAndroid Build Coastguard Worker int ChangeCurrentThreadDirectory(const char* path) {
102*6777b538SAndroid Build Coastguard Worker   return pthread_chdir_np(path);
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker // The recommended way to unset a per-thread cwd is to set a new value to an
106*6777b538SAndroid Build Coastguard Worker // invalid file descriptor, per libpthread-218.1.3/private/private.h.
ResetCurrentThreadDirectory()107*6777b538SAndroid Build Coastguard Worker int ResetCurrentThreadDirectory() {
108*6777b538SAndroid Build Coastguard Worker   return pthread_fchdir_np(-1);
109*6777b538SAndroid Build Coastguard Worker }
110*6777b538SAndroid Build Coastguard Worker #endif
111*6777b538SAndroid Build Coastguard Worker 
112*6777b538SAndroid Build Coastguard Worker struct GetAppOutputOptions {
113*6777b538SAndroid Build Coastguard Worker   // Whether to pipe stderr to stdout in |output|.
114*6777b538SAndroid Build Coastguard Worker   bool include_stderr = false;
115*6777b538SAndroid Build Coastguard Worker   // Caller-supplied string poiter for the output.
116*6777b538SAndroid Build Coastguard Worker   raw_ptr<std::string> output = nullptr;
117*6777b538SAndroid Build Coastguard Worker   // Result exit code of Process::Wait().
118*6777b538SAndroid Build Coastguard Worker   int exit_code = 0;
119*6777b538SAndroid Build Coastguard Worker };
120*6777b538SAndroid Build Coastguard Worker 
GetAppOutputInternal(const std::vector<std::string> & argv,GetAppOutputOptions * gao_options)121*6777b538SAndroid Build Coastguard Worker bool GetAppOutputInternal(const std::vector<std::string>& argv,
122*6777b538SAndroid Build Coastguard Worker                           GetAppOutputOptions* gao_options) {
123*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT0("base", "GetAppOutput");
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   ScopedFD read_fd, write_fd;
126*6777b538SAndroid Build Coastguard Worker   {
127*6777b538SAndroid Build Coastguard Worker     int pipefds[2];
128*6777b538SAndroid Build Coastguard Worker     if (pipe(pipefds) != 0) {
129*6777b538SAndroid Build Coastguard Worker       DPLOG(ERROR) << "pipe";
130*6777b538SAndroid Build Coastguard Worker       return false;
131*6777b538SAndroid Build Coastguard Worker     }
132*6777b538SAndroid Build Coastguard Worker     read_fd.reset(pipefds[0]);
133*6777b538SAndroid Build Coastguard Worker     write_fd.reset(pipefds[1]);
134*6777b538SAndroid Build Coastguard Worker   }
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker   LaunchOptions launch_options;
137*6777b538SAndroid Build Coastguard Worker   launch_options.fds_to_remap.emplace_back(write_fd.get(), STDOUT_FILENO);
138*6777b538SAndroid Build Coastguard Worker   if (gao_options->include_stderr) {
139*6777b538SAndroid Build Coastguard Worker     launch_options.fds_to_remap.emplace_back(write_fd.get(), STDERR_FILENO);
140*6777b538SAndroid Build Coastguard Worker   }
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker   Process process = LaunchProcess(argv, launch_options);
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker   // Close the parent process' write descriptor, so that EOF is generated in
145*6777b538SAndroid Build Coastguard Worker   // read loop below.
146*6777b538SAndroid Build Coastguard Worker   write_fd.reset();
147*6777b538SAndroid Build Coastguard Worker 
148*6777b538SAndroid Build Coastguard Worker   // Read the child's output before waiting for its exit, otherwise the pipe
149*6777b538SAndroid Build Coastguard Worker   // buffer may fill up if the process is producing a lot of output.
150*6777b538SAndroid Build Coastguard Worker   std::string* output = gao_options->output;
151*6777b538SAndroid Build Coastguard Worker   output->clear();
152*6777b538SAndroid Build Coastguard Worker 
153*6777b538SAndroid Build Coastguard Worker   const size_t kBufferSize = 1024;
154*6777b538SAndroid Build Coastguard Worker   size_t total_bytes_read = 0;
155*6777b538SAndroid Build Coastguard Worker   ssize_t read_this_pass = 0;
156*6777b538SAndroid Build Coastguard Worker   do {
157*6777b538SAndroid Build Coastguard Worker     output->resize(output->size() + kBufferSize);
158*6777b538SAndroid Build Coastguard Worker     read_this_pass = HANDLE_EINTR(
159*6777b538SAndroid Build Coastguard Worker         read(read_fd.get(), &(*output)[total_bytes_read], kBufferSize));
160*6777b538SAndroid Build Coastguard Worker     if (read_this_pass >= 0) {
161*6777b538SAndroid Build Coastguard Worker       total_bytes_read += static_cast<size_t>(read_this_pass);
162*6777b538SAndroid Build Coastguard Worker       output->resize(total_bytes_read);
163*6777b538SAndroid Build Coastguard Worker     }
164*6777b538SAndroid Build Coastguard Worker   } while (read_this_pass > 0);
165*6777b538SAndroid Build Coastguard Worker 
166*6777b538SAndroid Build Coastguard Worker   // It is okay to allow this process to wait on the launched process as a
167*6777b538SAndroid Build Coastguard Worker   // process launched with GetAppOutput*() shouldn't wait back on the process
168*6777b538SAndroid Build Coastguard Worker   // that launched it.
169*6777b538SAndroid Build Coastguard Worker   internal::GetAppOutputScopedAllowBaseSyncPrimitives allow_wait;
170*6777b538SAndroid Build Coastguard Worker   if (!process.WaitForExit(&gao_options->exit_code)) {
171*6777b538SAndroid Build Coastguard Worker     return false;
172*6777b538SAndroid Build Coastguard Worker   }
173*6777b538SAndroid Build Coastguard Worker 
174*6777b538SAndroid Build Coastguard Worker   return read_this_pass == 0;
175*6777b538SAndroid Build Coastguard Worker }
176*6777b538SAndroid Build Coastguard Worker 
177*6777b538SAndroid Build Coastguard Worker }  // namespace
178*6777b538SAndroid Build Coastguard Worker 
LaunchProcess(const CommandLine & cmdline,const LaunchOptions & options)179*6777b538SAndroid Build Coastguard Worker Process LaunchProcess(const CommandLine& cmdline,
180*6777b538SAndroid Build Coastguard Worker                       const LaunchOptions& options) {
181*6777b538SAndroid Build Coastguard Worker   return LaunchProcess(cmdline.argv(), options);
182*6777b538SAndroid Build Coastguard Worker }
183*6777b538SAndroid Build Coastguard Worker 
LaunchProcess(const std::vector<std::string> & argv,const LaunchOptions & options)184*6777b538SAndroid Build Coastguard Worker Process LaunchProcess(const std::vector<std::string>& argv,
185*6777b538SAndroid Build Coastguard Worker                       const LaunchOptions& options) {
186*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT0("base", "LaunchProcess");
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   PosixSpawnAttr attr;
189*6777b538SAndroid Build Coastguard Worker 
190*6777b538SAndroid Build Coastguard Worker   short flags = POSIX_SPAWN_CLOEXEC_DEFAULT;
191*6777b538SAndroid Build Coastguard Worker   if (options.new_process_group) {
192*6777b538SAndroid Build Coastguard Worker     flags |= POSIX_SPAWN_SETPGROUP;
193*6777b538SAndroid Build Coastguard Worker     DPSXCHECK(posix_spawnattr_setpgroup(attr.get(), 0));
194*6777b538SAndroid Build Coastguard Worker   }
195*6777b538SAndroid Build Coastguard Worker   DPSXCHECK(posix_spawnattr_setflags(attr.get(), flags));
196*6777b538SAndroid Build Coastguard Worker 
197*6777b538SAndroid Build Coastguard Worker   PosixSpawnFileActions file_actions;
198*6777b538SAndroid Build Coastguard Worker 
199*6777b538SAndroid Build Coastguard Worker   // Process file descriptors for the child. By default, LaunchProcess will
200*6777b538SAndroid Build Coastguard Worker   // open stdin to /dev/null and inherit stdout and stderr.
201*6777b538SAndroid Build Coastguard Worker   bool inherit_stdout = true, inherit_stderr = true;
202*6777b538SAndroid Build Coastguard Worker   bool null_stdin = true;
203*6777b538SAndroid Build Coastguard Worker   for (const auto& dup2_pair : options.fds_to_remap) {
204*6777b538SAndroid Build Coastguard Worker     if (dup2_pair.second == STDIN_FILENO) {
205*6777b538SAndroid Build Coastguard Worker       null_stdin = false;
206*6777b538SAndroid Build Coastguard Worker     } else if (dup2_pair.second == STDOUT_FILENO) {
207*6777b538SAndroid Build Coastguard Worker       inherit_stdout = false;
208*6777b538SAndroid Build Coastguard Worker     } else if (dup2_pair.second == STDERR_FILENO) {
209*6777b538SAndroid Build Coastguard Worker       inherit_stderr = false;
210*6777b538SAndroid Build Coastguard Worker     }
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker     if (dup2_pair.first == dup2_pair.second) {
213*6777b538SAndroid Build Coastguard Worker       file_actions.Inherit(dup2_pair.second);
214*6777b538SAndroid Build Coastguard Worker     } else {
215*6777b538SAndroid Build Coastguard Worker       file_actions.Dup2(dup2_pair.first, dup2_pair.second);
216*6777b538SAndroid Build Coastguard Worker     }
217*6777b538SAndroid Build Coastguard Worker   }
218*6777b538SAndroid Build Coastguard Worker 
219*6777b538SAndroid Build Coastguard Worker   if (null_stdin) {
220*6777b538SAndroid Build Coastguard Worker     file_actions.Open(STDIN_FILENO, "/dev/null", O_RDONLY);
221*6777b538SAndroid Build Coastguard Worker   }
222*6777b538SAndroid Build Coastguard Worker   if (inherit_stdout) {
223*6777b538SAndroid Build Coastguard Worker     file_actions.Inherit(STDOUT_FILENO);
224*6777b538SAndroid Build Coastguard Worker   }
225*6777b538SAndroid Build Coastguard Worker   if (inherit_stderr) {
226*6777b538SAndroid Build Coastguard Worker     file_actions.Inherit(STDERR_FILENO);
227*6777b538SAndroid Build Coastguard Worker   }
228*6777b538SAndroid Build Coastguard Worker 
229*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_MAC)
230*6777b538SAndroid Build Coastguard Worker   if (options.disclaim_responsibility) {
231*6777b538SAndroid Build Coastguard Worker     DPSXCHECK(responsibility_spawnattrs_setdisclaim(attr.get(), 1));
232*6777b538SAndroid Build Coastguard Worker   }
233*6777b538SAndroid Build Coastguard Worker #endif
234*6777b538SAndroid Build Coastguard Worker 
235*6777b538SAndroid Build Coastguard Worker   std::vector<char*> argv_cstr;
236*6777b538SAndroid Build Coastguard Worker   argv_cstr.reserve(argv.size() + 1);
237*6777b538SAndroid Build Coastguard Worker   for (const auto& arg : argv)
238*6777b538SAndroid Build Coastguard Worker     argv_cstr.push_back(const_cast<char*>(arg.c_str()));
239*6777b538SAndroid Build Coastguard Worker   argv_cstr.push_back(nullptr);
240*6777b538SAndroid Build Coastguard Worker 
241*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<char*[]> owned_environ;
242*6777b538SAndroid Build Coastguard Worker   char* empty_environ = nullptr;
243*6777b538SAndroid Build Coastguard Worker   char** new_environ =
244*6777b538SAndroid Build Coastguard Worker       options.clear_environment ? &empty_environ : *_NSGetEnviron();
245*6777b538SAndroid Build Coastguard Worker   if (!options.environment.empty()) {
246*6777b538SAndroid Build Coastguard Worker     owned_environ =
247*6777b538SAndroid Build Coastguard Worker         internal::AlterEnvironment(new_environ, options.environment);
248*6777b538SAndroid Build Coastguard Worker     new_environ = owned_environ.get();
249*6777b538SAndroid Build Coastguard Worker   }
250*6777b538SAndroid Build Coastguard Worker 
251*6777b538SAndroid Build Coastguard Worker   const char* executable_path = !options.real_path.empty()
252*6777b538SAndroid Build Coastguard Worker                                     ? options.real_path.value().c_str()
253*6777b538SAndroid Build Coastguard Worker                                     : argv_cstr[0];
254*6777b538SAndroid Build Coastguard Worker 
255*6777b538SAndroid Build Coastguard Worker   if (__builtin_available(macOS 11.0, *)) {
256*6777b538SAndroid Build Coastguard Worker     if (options.enable_cpu_security_mitigations) {
257*6777b538SAndroid Build Coastguard Worker       DPSXCHECK(posix_spawnattr_set_csm_np(attr.get(), POSIX_SPAWN_NP_CSM_ALL));
258*6777b538SAndroid Build Coastguard Worker     }
259*6777b538SAndroid Build Coastguard Worker   }
260*6777b538SAndroid Build Coastguard Worker 
261*6777b538SAndroid Build Coastguard Worker   if (!options.current_directory.empty()) {
262*6777b538SAndroid Build Coastguard Worker     const char* chdir_str = options.current_directory.value().c_str();
263*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_MAC)
264*6777b538SAndroid Build Coastguard Worker     file_actions.Chdir(chdir_str);
265*6777b538SAndroid Build Coastguard Worker #else
266*6777b538SAndroid Build Coastguard Worker     // If the chdir posix_spawn_file_actions extension is not available,
267*6777b538SAndroid Build Coastguard Worker     // change the thread-specific working directory. The new process will
268*6777b538SAndroid Build Coastguard Worker     // inherit it during posix_spawnp().
269*6777b538SAndroid Build Coastguard Worker     int rv = ChangeCurrentThreadDirectory(chdir_str);
270*6777b538SAndroid Build Coastguard Worker     if (rv != 0) {
271*6777b538SAndroid Build Coastguard Worker       DPLOG(ERROR) << "pthread_chdir_np";
272*6777b538SAndroid Build Coastguard Worker       return Process();
273*6777b538SAndroid Build Coastguard Worker     }
274*6777b538SAndroid Build Coastguard Worker #endif
275*6777b538SAndroid Build Coastguard Worker   }
276*6777b538SAndroid Build Coastguard Worker 
277*6777b538SAndroid Build Coastguard Worker   int rv;
278*6777b538SAndroid Build Coastguard Worker   pid_t pid;
279*6777b538SAndroid Build Coastguard Worker   {
280*6777b538SAndroid Build Coastguard Worker     const bool has_mach_ports_for_rendezvous =
281*6777b538SAndroid Build Coastguard Worker         !options.mach_ports_for_rendezvous.empty();
282*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS)
283*6777b538SAndroid Build Coastguard Worker     // This code is only used for the iOS simulator to launch tests. We do not
284*6777b538SAndroid Build Coastguard Worker     // support setting MachPorts on launch. You should look at
285*6777b538SAndroid Build Coastguard Worker     // content::ChildProcessLauncherHelper (for iOS) if you are trying to spawn
286*6777b538SAndroid Build Coastguard Worker     // a non-test and need ports.
287*6777b538SAndroid Build Coastguard Worker     CHECK(!has_mach_ports_for_rendezvous);
288*6777b538SAndroid Build Coastguard Worker #else
289*6777b538SAndroid Build Coastguard Worker     // If |options.mach_ports_for_rendezvous| is specified : the server's lock
290*6777b538SAndroid Build Coastguard Worker     // must be held for the duration of posix_spawnp() so that new child's PID
291*6777b538SAndroid Build Coastguard Worker     // can be recorded with the set of ports.
292*6777b538SAndroid Build Coastguard Worker     AutoLockMaybe rendezvous_lock(
293*6777b538SAndroid Build Coastguard Worker         has_mach_ports_for_rendezvous
294*6777b538SAndroid Build Coastguard Worker             ? &MachPortRendezvousServer::GetInstance()->GetLock()
295*6777b538SAndroid Build Coastguard Worker             : nullptr);
296*6777b538SAndroid Build Coastguard Worker #endif
297*6777b538SAndroid Build Coastguard Worker     // Use posix_spawnp as some callers expect to have PATH consulted.
298*6777b538SAndroid Build Coastguard Worker     rv = posix_spawnp(&pid, executable_path, file_actions.get(), attr.get(),
299*6777b538SAndroid Build Coastguard Worker                       &argv_cstr[0], new_environ);
300*6777b538SAndroid Build Coastguard Worker 
301*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_IOS)
302*6777b538SAndroid Build Coastguard Worker     if (has_mach_ports_for_rendezvous) {
303*6777b538SAndroid Build Coastguard Worker       if (rv == 0) {
304*6777b538SAndroid Build Coastguard Worker         MachPortRendezvousServer::GetInstance()->GetLock().AssertAcquired();
305*6777b538SAndroid Build Coastguard Worker         MachPortRendezvousServer::GetInstance()->RegisterPortsForPid(
306*6777b538SAndroid Build Coastguard Worker             pid, options.mach_ports_for_rendezvous);
307*6777b538SAndroid Build Coastguard Worker       } else {
308*6777b538SAndroid Build Coastguard Worker         // Because |options| is const-ref, the collection has to be copied here.
309*6777b538SAndroid Build Coastguard Worker         // The caller expects to relinquish ownership of any strong rights if
310*6777b538SAndroid Build Coastguard Worker         // LaunchProcess() were to succeed, so these rights should be manually
311*6777b538SAndroid Build Coastguard Worker         // destroyed on failure.
312*6777b538SAndroid Build Coastguard Worker         MachPortsForRendezvous ports = options.mach_ports_for_rendezvous;
313*6777b538SAndroid Build Coastguard Worker         for (auto& port : ports) {
314*6777b538SAndroid Build Coastguard Worker           port.second.Destroy();
315*6777b538SAndroid Build Coastguard Worker         }
316*6777b538SAndroid Build Coastguard Worker       }
317*6777b538SAndroid Build Coastguard Worker     }
318*6777b538SAndroid Build Coastguard Worker #endif
319*6777b538SAndroid Build Coastguard Worker   }
320*6777b538SAndroid Build Coastguard Worker 
321*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_MAC)
322*6777b538SAndroid Build Coastguard Worker   // Restore the thread's working directory if it was changed.
323*6777b538SAndroid Build Coastguard Worker   if (!options.current_directory.empty()) {
324*6777b538SAndroid Build Coastguard Worker     ResetCurrentThreadDirectory();
325*6777b538SAndroid Build Coastguard Worker   }
326*6777b538SAndroid Build Coastguard Worker #endif
327*6777b538SAndroid Build Coastguard Worker 
328*6777b538SAndroid Build Coastguard Worker   if (rv != 0) {
329*6777b538SAndroid Build Coastguard Worker     DLOG(ERROR) << "posix_spawnp(" << executable_path << "): -" << rv << " "
330*6777b538SAndroid Build Coastguard Worker                 << strerror(rv);
331*6777b538SAndroid Build Coastguard Worker     return Process();
332*6777b538SAndroid Build Coastguard Worker   }
333*6777b538SAndroid Build Coastguard Worker 
334*6777b538SAndroid Build Coastguard Worker   if (options.wait) {
335*6777b538SAndroid Build Coastguard Worker     // While this isn't strictly disk IO, waiting for another process to
336*6777b538SAndroid Build Coastguard Worker     // finish is the sort of thing ThreadRestrictions is trying to prevent.
337*6777b538SAndroid Build Coastguard Worker     ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
338*6777b538SAndroid Build Coastguard Worker     pid_t ret = HANDLE_EINTR(waitpid(pid, nullptr, 0));
339*6777b538SAndroid Build Coastguard Worker     DPCHECK(ret > 0);
340*6777b538SAndroid Build Coastguard Worker   }
341*6777b538SAndroid Build Coastguard Worker 
342*6777b538SAndroid Build Coastguard Worker   return Process(pid);
343*6777b538SAndroid Build Coastguard Worker }
344*6777b538SAndroid Build Coastguard Worker 
GetAppOutput(const CommandLine & cl,std::string * output)345*6777b538SAndroid Build Coastguard Worker bool GetAppOutput(const CommandLine& cl, std::string* output) {
346*6777b538SAndroid Build Coastguard Worker   return GetAppOutput(cl.argv(), output);
347*6777b538SAndroid Build Coastguard Worker }
348*6777b538SAndroid Build Coastguard Worker 
GetAppOutputAndError(const CommandLine & cl,std::string * output)349*6777b538SAndroid Build Coastguard Worker bool GetAppOutputAndError(const CommandLine& cl, std::string* output) {
350*6777b538SAndroid Build Coastguard Worker   return GetAppOutputAndError(cl.argv(), output);
351*6777b538SAndroid Build Coastguard Worker }
352*6777b538SAndroid Build Coastguard Worker 
GetAppOutputWithExitCode(const CommandLine & cl,std::string * output,int * exit_code)353*6777b538SAndroid Build Coastguard Worker bool GetAppOutputWithExitCode(const CommandLine& cl,
354*6777b538SAndroid Build Coastguard Worker                               std::string* output,
355*6777b538SAndroid Build Coastguard Worker                               int* exit_code) {
356*6777b538SAndroid Build Coastguard Worker   GetAppOutputOptions options;
357*6777b538SAndroid Build Coastguard Worker   options.output = output;
358*6777b538SAndroid Build Coastguard Worker   bool rv = GetAppOutputInternal(cl.argv(), &options);
359*6777b538SAndroid Build Coastguard Worker   *exit_code = options.exit_code;
360*6777b538SAndroid Build Coastguard Worker   return rv;
361*6777b538SAndroid Build Coastguard Worker }
362*6777b538SAndroid Build Coastguard Worker 
GetAppOutput(const std::vector<std::string> & argv,std::string * output)363*6777b538SAndroid Build Coastguard Worker bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) {
364*6777b538SAndroid Build Coastguard Worker   GetAppOutputOptions options;
365*6777b538SAndroid Build Coastguard Worker   options.output = output;
366*6777b538SAndroid Build Coastguard Worker   return GetAppOutputInternal(argv, &options) &&
367*6777b538SAndroid Build Coastguard Worker          options.exit_code == EXIT_SUCCESS;
368*6777b538SAndroid Build Coastguard Worker }
369*6777b538SAndroid Build Coastguard Worker 
GetAppOutputAndError(const std::vector<std::string> & argv,std::string * output)370*6777b538SAndroid Build Coastguard Worker bool GetAppOutputAndError(const std::vector<std::string>& argv,
371*6777b538SAndroid Build Coastguard Worker                           std::string* output) {
372*6777b538SAndroid Build Coastguard Worker   GetAppOutputOptions options;
373*6777b538SAndroid Build Coastguard Worker   options.include_stderr = true;
374*6777b538SAndroid Build Coastguard Worker   options.output = output;
375*6777b538SAndroid Build Coastguard Worker   return GetAppOutputInternal(argv, &options) &&
376*6777b538SAndroid Build Coastguard Worker          options.exit_code == EXIT_SUCCESS;
377*6777b538SAndroid Build Coastguard Worker }
378*6777b538SAndroid Build Coastguard Worker 
RaiseProcessToHighPriority()379*6777b538SAndroid Build Coastguard Worker void RaiseProcessToHighPriority() {
380*6777b538SAndroid Build Coastguard Worker   // Historically this has not been implemented on POSIX and macOS. This could
381*6777b538SAndroid Build Coastguard Worker   // influence the Mach task policy in the future.
382*6777b538SAndroid Build Coastguard Worker }
383*6777b538SAndroid Build Coastguard Worker 
384*6777b538SAndroid Build Coastguard Worker }  // namespace base
385