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