xref: /aosp_15_r20/external/cronet/base/process/launch_fuchsia.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 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 <tuple>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <lib/fdio/limits.h>
10*6777b538SAndroid Build Coastguard Worker #include <lib/fdio/namespace.h>
11*6777b538SAndroid Build Coastguard Worker #include <lib/fdio/spawn.h>
12*6777b538SAndroid Build Coastguard Worker #include <lib/zx/job.h>
13*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
14*6777b538SAndroid Build Coastguard Worker #include <unistd.h>
15*6777b538SAndroid Build Coastguard Worker #include <zircon/processargs.h>
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/fuchsia/default_job.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/fuchsia/file_utils.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/fuchsia/fuchsia_logging.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/process/environment_internal.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/scoped_generic.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker namespace base {
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker namespace {
32*6777b538SAndroid Build Coastguard Worker 
GetAppOutputInternal(const CommandLine & cmd_line,bool include_stderr,std::string * output,int * exit_code)33*6777b538SAndroid Build Coastguard Worker bool GetAppOutputInternal(const CommandLine& cmd_line,
34*6777b538SAndroid Build Coastguard Worker                           bool include_stderr,
35*6777b538SAndroid Build Coastguard Worker                           std::string* output,
36*6777b538SAndroid Build Coastguard Worker                           int* exit_code) {
37*6777b538SAndroid Build Coastguard Worker   DCHECK(exit_code);
38*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT0("base", "GetAppOutput");
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker   LaunchOptions options;
41*6777b538SAndroid Build Coastguard Worker 
42*6777b538SAndroid Build Coastguard Worker   // LaunchProcess will automatically clone any stdio fd we do not explicitly
43*6777b538SAndroid Build Coastguard Worker   // map.
44*6777b538SAndroid Build Coastguard Worker   int pipe_fd[2];
45*6777b538SAndroid Build Coastguard Worker   if (pipe(pipe_fd) < 0)
46*6777b538SAndroid Build Coastguard Worker     return false;
47*6777b538SAndroid Build Coastguard Worker   options.fds_to_remap.emplace_back(pipe_fd[1], STDOUT_FILENO);
48*6777b538SAndroid Build Coastguard Worker   if (include_stderr)
49*6777b538SAndroid Build Coastguard Worker     options.fds_to_remap.emplace_back(pipe_fd[1], STDERR_FILENO);
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker   Process process = LaunchProcess(cmd_line, options);
52*6777b538SAndroid Build Coastguard Worker   close(pipe_fd[1]);
53*6777b538SAndroid Build Coastguard Worker   if (!process.IsValid()) {
54*6777b538SAndroid Build Coastguard Worker     close(pipe_fd[0]);
55*6777b538SAndroid Build Coastguard Worker     return false;
56*6777b538SAndroid Build Coastguard Worker   }
57*6777b538SAndroid Build Coastguard Worker 
58*6777b538SAndroid Build Coastguard Worker   output->clear();
59*6777b538SAndroid Build Coastguard Worker   for (;;) {
60*6777b538SAndroid Build Coastguard Worker     char buffer[256];
61*6777b538SAndroid Build Coastguard Worker     ssize_t bytes_read = read(pipe_fd[0], buffer, sizeof(buffer));
62*6777b538SAndroid Build Coastguard Worker     if (bytes_read <= 0)
63*6777b538SAndroid Build Coastguard Worker       break;
64*6777b538SAndroid Build Coastguard Worker     output->append(buffer, static_cast<size_t>(bytes_read));
65*6777b538SAndroid Build Coastguard Worker   }
66*6777b538SAndroid Build Coastguard Worker   close(pipe_fd[0]);
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker   // It is okay to allow this process to wait on the launched process as a
69*6777b538SAndroid Build Coastguard Worker   // process launched with GetAppOutput*() shouldn't wait back on the process
70*6777b538SAndroid Build Coastguard Worker   // that launched it.
71*6777b538SAndroid Build Coastguard Worker   internal::GetAppOutputScopedAllowBaseSyncPrimitives allow_wait;
72*6777b538SAndroid Build Coastguard Worker   return process.WaitForExit(exit_code);
73*6777b538SAndroid Build Coastguard Worker }
74*6777b538SAndroid Build Coastguard Worker 
FdioSpawnAction(uint32_t action)75*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t FdioSpawnAction(uint32_t action) {
76*6777b538SAndroid Build Coastguard Worker   fdio_spawn_action_t new_action = {};
77*6777b538SAndroid Build Coastguard Worker   new_action.action = action;
78*6777b538SAndroid Build Coastguard Worker   return new_action;
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker 
FdioSpawnActionCloneFd(int local_fd,int target_fd)81*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t FdioSpawnActionCloneFd(int local_fd, int target_fd) {
82*6777b538SAndroid Build Coastguard Worker   fdio_spawn_action_t action = FdioSpawnAction(FDIO_SPAWN_ACTION_CLONE_FD);
83*6777b538SAndroid Build Coastguard Worker   action.fd.local_fd = local_fd;
84*6777b538SAndroid Build Coastguard Worker   action.fd.target_fd = target_fd;
85*6777b538SAndroid Build Coastguard Worker   return action;
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker 
FdioSpawnActionAddNamespaceEntry(const char * prefix,zx_handle_t handle)88*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t FdioSpawnActionAddNamespaceEntry(const char* prefix,
89*6777b538SAndroid Build Coastguard Worker                                                      zx_handle_t handle) {
90*6777b538SAndroid Build Coastguard Worker   fdio_spawn_action_t action = FdioSpawnAction(FDIO_SPAWN_ACTION_ADD_NS_ENTRY);
91*6777b538SAndroid Build Coastguard Worker   action.ns.prefix = prefix;
92*6777b538SAndroid Build Coastguard Worker   action.ns.handle = handle;
93*6777b538SAndroid Build Coastguard Worker   return action;
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker 
FdioSpawnActionAddHandle(uint32_t id,zx_handle_t handle)96*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t FdioSpawnActionAddHandle(uint32_t id, zx_handle_t handle) {
97*6777b538SAndroid Build Coastguard Worker   fdio_spawn_action_t action = FdioSpawnAction(FDIO_SPAWN_ACTION_ADD_HANDLE);
98*6777b538SAndroid Build Coastguard Worker   action.h.id = id;
99*6777b538SAndroid Build Coastguard Worker   action.h.handle = handle;
100*6777b538SAndroid Build Coastguard Worker   return action;
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker 
FdioSpawnActionSetName(const char * name)103*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t FdioSpawnActionSetName(const char* name) {
104*6777b538SAndroid Build Coastguard Worker   fdio_spawn_action_t action = FdioSpawnAction(FDIO_SPAWN_ACTION_SET_NAME);
105*6777b538SAndroid Build Coastguard Worker   action.name.data = name;
106*6777b538SAndroid Build Coastguard Worker   return action;
107*6777b538SAndroid Build Coastguard Worker }
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker }  // namespace
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker // static
AddHandleToTransfer(HandlesToTransferVector * handles_to_transfer,zx_handle_t handle)112*6777b538SAndroid Build Coastguard Worker uint32_t LaunchOptions::AddHandleToTransfer(
113*6777b538SAndroid Build Coastguard Worker     HandlesToTransferVector* handles_to_transfer,
114*6777b538SAndroid Build Coastguard Worker     zx_handle_t handle) {
115*6777b538SAndroid Build Coastguard Worker   CHECK_LE(handles_to_transfer->size(), std::numeric_limits<uint16_t>::max())
116*6777b538SAndroid Build Coastguard Worker       << "Number of handles to transfer exceeds total allowed";
117*6777b538SAndroid Build Coastguard Worker   auto handle_id =
118*6777b538SAndroid Build Coastguard Worker       static_cast<uint32_t>(PA_HND(PA_USER1, handles_to_transfer->size()));
119*6777b538SAndroid Build Coastguard Worker   handles_to_transfer->push_back({handle_id, handle});
120*6777b538SAndroid Build Coastguard Worker   return handle_id;
121*6777b538SAndroid Build Coastguard Worker }
122*6777b538SAndroid Build Coastguard Worker 
LaunchProcess(const CommandLine & cmdline,const LaunchOptions & options)123*6777b538SAndroid Build Coastguard Worker Process LaunchProcess(const CommandLine& cmdline,
124*6777b538SAndroid Build Coastguard Worker                       const LaunchOptions& options) {
125*6777b538SAndroid Build Coastguard Worker   return LaunchProcess(cmdline.argv(), options);
126*6777b538SAndroid Build Coastguard Worker }
127*6777b538SAndroid Build Coastguard Worker 
LaunchProcess(const std::vector<std::string> & argv,const LaunchOptions & options)128*6777b538SAndroid Build Coastguard Worker Process LaunchProcess(const std::vector<std::string>& argv,
129*6777b538SAndroid Build Coastguard Worker                       const LaunchOptions& options) {
130*6777b538SAndroid Build Coastguard Worker   // fdio_spawn_etc() accepts an array of |fdio_spawn_action_t|, describing
131*6777b538SAndroid Build Coastguard Worker   // namespace entries, descriptors and handles to launch the child process
132*6777b538SAndroid Build Coastguard Worker   // with. |fdio_spawn_action_t| does not own any values assigned to its
133*6777b538SAndroid Build Coastguard Worker   // members, so strings assigned to members must be valid through the
134*6777b538SAndroid Build Coastguard Worker   // fdio_spawn_etc() call.
135*6777b538SAndroid Build Coastguard Worker   std::vector<fdio_spawn_action_t> spawn_actions;
136*6777b538SAndroid Build Coastguard Worker 
137*6777b538SAndroid Build Coastguard Worker   // Handles to be transferred to the child are owned by this vector, so that
138*6777b538SAndroid Build Coastguard Worker   // they they are closed on early-exit, and can be release()d otherwise.
139*6777b538SAndroid Build Coastguard Worker   std::vector<zx::handle> transferred_handles;
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker   // Add caller-supplied handles for transfer. We must do this first to ensure
142*6777b538SAndroid Build Coastguard Worker   // that the handles are consumed even if some later step fails.
143*6777b538SAndroid Build Coastguard Worker   for (const auto& id_and_handle : options.handles_to_transfer) {
144*6777b538SAndroid Build Coastguard Worker     spawn_actions.push_back(
145*6777b538SAndroid Build Coastguard Worker         FdioSpawnActionAddHandle(id_and_handle.id, id_and_handle.handle));
146*6777b538SAndroid Build Coastguard Worker     transferred_handles.emplace_back(id_and_handle.handle);
147*6777b538SAndroid Build Coastguard Worker   }
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker   // Determine the job under which to launch the new process.
150*6777b538SAndroid Build Coastguard Worker   zx::unowned_job job = options.job_handle != ZX_HANDLE_INVALID
151*6777b538SAndroid Build Coastguard Worker                             ? zx::unowned_job(options.job_handle)
152*6777b538SAndroid Build Coastguard Worker                             : GetDefaultJob();
153*6777b538SAndroid Build Coastguard Worker   DCHECK(job->is_valid());
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker   // Construct an |argv| array of C-strings from the supplied std::strings.
156*6777b538SAndroid Build Coastguard Worker   std::vector<const char*> argv_cstr;
157*6777b538SAndroid Build Coastguard Worker   argv_cstr.reserve(argv.size() + 1);
158*6777b538SAndroid Build Coastguard Worker   for (const auto& arg : argv)
159*6777b538SAndroid Build Coastguard Worker     argv_cstr.push_back(arg.c_str());
160*6777b538SAndroid Build Coastguard Worker   argv_cstr.push_back(nullptr);
161*6777b538SAndroid Build Coastguard Worker 
162*6777b538SAndroid Build Coastguard Worker   // If |environment| is set then it contains values to set/replace to create
163*6777b538SAndroid Build Coastguard Worker   // the new process' environment.
164*6777b538SAndroid Build Coastguard Worker   EnvironmentMap environ_modifications = options.environment;
165*6777b538SAndroid Build Coastguard Worker 
166*6777b538SAndroid Build Coastguard Worker   // "PWD" is set in the new process' environment, to one of:
167*6777b538SAndroid Build Coastguard Worker   // 1. The value of |current_directory|, if set.
168*6777b538SAndroid Build Coastguard Worker   // 2. The value specified in |environment|, if any.
169*6777b538SAndroid Build Coastguard Worker   // 3. The current process' current working directory, if known.
170*6777b538SAndroid Build Coastguard Worker   if (!options.current_directory.empty()) {
171*6777b538SAndroid Build Coastguard Worker     environ_modifications["PWD"] = options.current_directory.value();
172*6777b538SAndroid Build Coastguard Worker   } else if (environ_modifications.find("PWD") == environ_modifications.end()) {
173*6777b538SAndroid Build Coastguard Worker     FilePath cwd;
174*6777b538SAndroid Build Coastguard Worker     if (GetCurrentDirectory(&cwd)) {
175*6777b538SAndroid Build Coastguard Worker       environ_modifications["PWD"] = cwd.value();
176*6777b538SAndroid Build Coastguard Worker     }
177*6777b538SAndroid Build Coastguard Worker   }
178*6777b538SAndroid Build Coastguard Worker 
179*6777b538SAndroid Build Coastguard Worker   // By default the calling process' environment is copied, and the collated
180*6777b538SAndroid Build Coastguard Worker   // modifications applied, to create the new process' environment. If
181*6777b538SAndroid Build Coastguard Worker   // |clear_environment| is set then only the collated modifications are used.
182*6777b538SAndroid Build Coastguard Worker   char* const kEmptyEnviron = nullptr;
183*6777b538SAndroid Build Coastguard Worker   char* const* old_environ =
184*6777b538SAndroid Build Coastguard Worker       options.clear_environment ? &kEmptyEnviron : environ;
185*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<char*[]> new_environ =
186*6777b538SAndroid Build Coastguard Worker       internal::AlterEnvironment(old_environ, environ_modifications);
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   // Always clone the library loader service and UTC clock to new processes,
189*6777b538SAndroid Build Coastguard Worker   // in addition to any flags specified by the caller.
190*6777b538SAndroid Build Coastguard Worker   uint32_t spawn_flags = FDIO_SPAWN_DEFAULT_LDSVC | FDIO_SPAWN_CLONE_UTC_CLOCK |
191*6777b538SAndroid Build Coastguard Worker                          options.spawn_flags;
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker   // Add actions to clone handles for any specified paths into the new process'
194*6777b538SAndroid Build Coastguard Worker   // namespace.
195*6777b538SAndroid Build Coastguard Worker   if (!options.paths_to_clone.empty() || !options.paths_to_transfer.empty()) {
196*6777b538SAndroid Build Coastguard Worker     DCHECK((options.spawn_flags & FDIO_SPAWN_CLONE_NAMESPACE) == 0);
197*6777b538SAndroid Build Coastguard Worker     transferred_handles.reserve(transferred_handles.size() +
198*6777b538SAndroid Build Coastguard Worker                                 options.paths_to_clone.size() +
199*6777b538SAndroid Build Coastguard Worker                                 options.paths_to_transfer.size());
200*6777b538SAndroid Build Coastguard Worker 
201*6777b538SAndroid Build Coastguard Worker     for (const auto& path_to_transfer : options.paths_to_transfer) {
202*6777b538SAndroid Build Coastguard Worker       zx::handle handle(path_to_transfer.handle);
203*6777b538SAndroid Build Coastguard Worker       spawn_actions.push_back(FdioSpawnActionAddNamespaceEntry(
204*6777b538SAndroid Build Coastguard Worker           path_to_transfer.path.value().c_str(), handle.get()));
205*6777b538SAndroid Build Coastguard Worker       transferred_handles.push_back(std::move(handle));
206*6777b538SAndroid Build Coastguard Worker     }
207*6777b538SAndroid Build Coastguard Worker 
208*6777b538SAndroid Build Coastguard Worker     for (const auto& path_to_clone : options.paths_to_clone) {
209*6777b538SAndroid Build Coastguard Worker       fidl::InterfaceHandle<::fuchsia::io::Directory> directory =
210*6777b538SAndroid Build Coastguard Worker           base::OpenDirectoryHandle(path_to_clone);
211*6777b538SAndroid Build Coastguard Worker       if (!directory) {
212*6777b538SAndroid Build Coastguard Worker         LOG(WARNING) << "Could not open handle for path: " << path_to_clone;
213*6777b538SAndroid Build Coastguard Worker         return base::Process();
214*6777b538SAndroid Build Coastguard Worker       }
215*6777b538SAndroid Build Coastguard Worker 
216*6777b538SAndroid Build Coastguard Worker       zx::handle handle = directory.TakeChannel();
217*6777b538SAndroid Build Coastguard Worker 
218*6777b538SAndroid Build Coastguard Worker       spawn_actions.push_back(FdioSpawnActionAddNamespaceEntry(
219*6777b538SAndroid Build Coastguard Worker           path_to_clone.value().c_str(), handle.get()));
220*6777b538SAndroid Build Coastguard Worker       transferred_handles.push_back(std::move(handle));
221*6777b538SAndroid Build Coastguard Worker     }
222*6777b538SAndroid Build Coastguard Worker   }
223*6777b538SAndroid Build Coastguard Worker 
224*6777b538SAndroid Build Coastguard Worker   // Add any file-descriptors to be cloned into the new process.
225*6777b538SAndroid Build Coastguard Worker   // Note that if FDIO_SPAWN_CLONE_STDIO is set, then any stdio entries in
226*6777b538SAndroid Build Coastguard Worker   // |fds_to_remap| will be used in place of the parent process' descriptors.
227*6777b538SAndroid Build Coastguard Worker   for (const auto& src_target : options.fds_to_remap) {
228*6777b538SAndroid Build Coastguard Worker     spawn_actions.push_back(
229*6777b538SAndroid Build Coastguard Worker         FdioSpawnActionCloneFd(src_target.first, src_target.second));
230*6777b538SAndroid Build Coastguard Worker   }
231*6777b538SAndroid Build Coastguard Worker 
232*6777b538SAndroid Build Coastguard Worker   // If |process_name_suffix| is specified then set process name as
233*6777b538SAndroid Build Coastguard Worker   // "<file_name><suffix>", otherwise leave the default value.
234*6777b538SAndroid Build Coastguard Worker   std::string process_name;  // Must outlive the fdio_spawn_etc() call.
235*6777b538SAndroid Build Coastguard Worker   if (!options.process_name_suffix.empty()) {
236*6777b538SAndroid Build Coastguard Worker     process_name = base::FilePath(argv[0]).BaseName().value() +
237*6777b538SAndroid Build Coastguard Worker                    options.process_name_suffix;
238*6777b538SAndroid Build Coastguard Worker     spawn_actions.push_back(FdioSpawnActionSetName(process_name.c_str()));
239*6777b538SAndroid Build Coastguard Worker   }
240*6777b538SAndroid Build Coastguard Worker 
241*6777b538SAndroid Build Coastguard Worker   zx::process process_handle;
242*6777b538SAndroid Build Coastguard Worker   // fdio_spawn_etc() will write a null-terminated scring to |error_message| in
243*6777b538SAndroid Build Coastguard Worker   // case of failure, so we avoid unnecessarily initializing it here.
244*6777b538SAndroid Build Coastguard Worker   char error_message[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
245*6777b538SAndroid Build Coastguard Worker   zx_status_t status = fdio_spawn_etc(
246*6777b538SAndroid Build Coastguard Worker       job->get(), spawn_flags, argv_cstr[0], argv_cstr.data(),
247*6777b538SAndroid Build Coastguard Worker       new_environ.get(), spawn_actions.size(), spawn_actions.data(),
248*6777b538SAndroid Build Coastguard Worker       process_handle.reset_and_get_address(), error_message);
249*6777b538SAndroid Build Coastguard Worker 
250*6777b538SAndroid Build Coastguard Worker   // fdio_spawn_etc() will close all handles specified in add-handle actions,
251*6777b538SAndroid Build Coastguard Worker   // regardless of whether it succeeds or fails, so release our copies.
252*6777b538SAndroid Build Coastguard Worker   for (auto& transferred_handle : transferred_handles)
253*6777b538SAndroid Build Coastguard Worker     std::ignore = transferred_handle.release();
254*6777b538SAndroid Build Coastguard Worker 
255*6777b538SAndroid Build Coastguard Worker   if (status != ZX_OK) {
256*6777b538SAndroid Build Coastguard Worker     ZX_LOG(ERROR, status) << "fdio_spawn: " << error_message;
257*6777b538SAndroid Build Coastguard Worker     return Process();
258*6777b538SAndroid Build Coastguard Worker   }
259*6777b538SAndroid Build Coastguard Worker 
260*6777b538SAndroid Build Coastguard Worker   // Wrap the handle into a Process, and wait for it to terminate, if requested.
261*6777b538SAndroid Build Coastguard Worker   Process process(process_handle.release());
262*6777b538SAndroid Build Coastguard Worker   if (options.wait) {
263*6777b538SAndroid Build Coastguard Worker     status = zx_object_wait_one(process.Handle(), ZX_TASK_TERMINATED,
264*6777b538SAndroid Build Coastguard Worker                                 ZX_TIME_INFINITE, nullptr);
265*6777b538SAndroid Build Coastguard Worker     ZX_DCHECK(status == ZX_OK, status) << "zx_object_wait_one";
266*6777b538SAndroid Build Coastguard Worker   }
267*6777b538SAndroid Build Coastguard Worker 
268*6777b538SAndroid Build Coastguard Worker   return process;
269*6777b538SAndroid Build Coastguard Worker }
270*6777b538SAndroid Build Coastguard Worker 
GetAppOutput(const CommandLine & cl,std::string * output)271*6777b538SAndroid Build Coastguard Worker bool GetAppOutput(const CommandLine& cl, std::string* output) {
272*6777b538SAndroid Build Coastguard Worker   int exit_code;
273*6777b538SAndroid Build Coastguard Worker   bool result = GetAppOutputInternal(cl, false, output, &exit_code);
274*6777b538SAndroid Build Coastguard Worker   return result && exit_code == EXIT_SUCCESS;
275*6777b538SAndroid Build Coastguard Worker }
276*6777b538SAndroid Build Coastguard Worker 
GetAppOutput(const std::vector<std::string> & argv,std::string * output)277*6777b538SAndroid Build Coastguard Worker bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) {
278*6777b538SAndroid Build Coastguard Worker   return GetAppOutput(CommandLine(argv), output);
279*6777b538SAndroid Build Coastguard Worker }
280*6777b538SAndroid Build Coastguard Worker 
GetAppOutputAndError(const CommandLine & cl,std::string * output)281*6777b538SAndroid Build Coastguard Worker bool GetAppOutputAndError(const CommandLine& cl, std::string* output) {
282*6777b538SAndroid Build Coastguard Worker   int exit_code;
283*6777b538SAndroid Build Coastguard Worker   bool result = GetAppOutputInternal(cl, true, output, &exit_code);
284*6777b538SAndroid Build Coastguard Worker   return result && exit_code == EXIT_SUCCESS;
285*6777b538SAndroid Build Coastguard Worker }
286*6777b538SAndroid Build Coastguard Worker 
GetAppOutputAndError(const std::vector<std::string> & argv,std::string * output)287*6777b538SAndroid Build Coastguard Worker bool GetAppOutputAndError(const std::vector<std::string>& argv,
288*6777b538SAndroid Build Coastguard Worker                           std::string* output) {
289*6777b538SAndroid Build Coastguard Worker   return GetAppOutputAndError(CommandLine(argv), output);
290*6777b538SAndroid Build Coastguard Worker }
291*6777b538SAndroid Build Coastguard Worker 
GetAppOutputWithExitCode(const CommandLine & cl,std::string * output,int * exit_code)292*6777b538SAndroid Build Coastguard Worker bool GetAppOutputWithExitCode(const CommandLine& cl,
293*6777b538SAndroid Build Coastguard Worker                               std::string* output,
294*6777b538SAndroid Build Coastguard Worker                               int* exit_code) {
295*6777b538SAndroid Build Coastguard Worker   // Contrary to GetAppOutput(), |true| return here means that the process was
296*6777b538SAndroid Build Coastguard Worker   // launched and the exit code was waited upon successfully, but not
297*6777b538SAndroid Build Coastguard Worker   // necessarily that the exit code was EXIT_SUCCESS.
298*6777b538SAndroid Build Coastguard Worker   return GetAppOutputInternal(cl, false, output, exit_code);
299*6777b538SAndroid Build Coastguard Worker }
300*6777b538SAndroid Build Coastguard Worker 
RaiseProcessToHighPriority()301*6777b538SAndroid Build Coastguard Worker void RaiseProcessToHighPriority() {
302*6777b538SAndroid Build Coastguard Worker   // Fuchsia doesn't provide an API to change process priority.
303*6777b538SAndroid Build Coastguard Worker }
304*6777b538SAndroid Build Coastguard Worker 
305*6777b538SAndroid Build Coastguard Worker }  // namespace base
306