xref: /aosp_15_r20/system/update_engine/common/subprocess.cc (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
1*5a923131SAndroid Build Coastguard Worker //
2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2012 The Android Open Source Project
3*5a923131SAndroid Build Coastguard Worker //
4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*5a923131SAndroid Build Coastguard Worker //
8*5a923131SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*5a923131SAndroid Build Coastguard Worker //
10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*5a923131SAndroid Build Coastguard Worker // limitations under the License.
15*5a923131SAndroid Build Coastguard Worker //
16*5a923131SAndroid Build Coastguard Worker 
17*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/subprocess.h"
18*5a923131SAndroid Build Coastguard Worker 
19*5a923131SAndroid Build Coastguard Worker #include <fcntl.h>
20*5a923131SAndroid Build Coastguard Worker #include <stdlib.h>
21*5a923131SAndroid Build Coastguard Worker #include <string.h>
22*5a923131SAndroid Build Coastguard Worker #include <unistd.h>
23*5a923131SAndroid Build Coastguard Worker 
24*5a923131SAndroid Build Coastguard Worker #include <chrono>
25*5a923131SAndroid Build Coastguard Worker #include <memory>
26*5a923131SAndroid Build Coastguard Worker #include <string>
27*5a923131SAndroid Build Coastguard Worker #include <utility>
28*5a923131SAndroid Build Coastguard Worker #include <vector>
29*5a923131SAndroid Build Coastguard Worker 
30*5a923131SAndroid Build Coastguard Worker #include <base/bind.h>
31*5a923131SAndroid Build Coastguard Worker #include <base/logging.h>
32*5a923131SAndroid Build Coastguard Worker #include <base/posix/eintr_wrapper.h>
33*5a923131SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
34*5a923131SAndroid Build Coastguard Worker #include <brillo/secure_blob.h>
35*5a923131SAndroid Build Coastguard Worker 
36*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/utils.h"
37*5a923131SAndroid Build Coastguard Worker 
38*5a923131SAndroid Build Coastguard Worker using brillo::MessageLoop;
39*5a923131SAndroid Build Coastguard Worker using std::string;
40*5a923131SAndroid Build Coastguard Worker using std::unique_ptr;
41*5a923131SAndroid Build Coastguard Worker using std::vector;
42*5a923131SAndroid Build Coastguard Worker 
43*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine {
44*5a923131SAndroid Build Coastguard Worker 
45*5a923131SAndroid Build Coastguard Worker namespace {
46*5a923131SAndroid Build Coastguard Worker 
SetupChild(const std::map<string,string> & env,uint32_t flags)47*5a923131SAndroid Build Coastguard Worker bool SetupChild(const std::map<string, string>& env, uint32_t flags) {
48*5a923131SAndroid Build Coastguard Worker   // Setup the environment variables.
49*5a923131SAndroid Build Coastguard Worker   clearenv();
50*5a923131SAndroid Build Coastguard Worker   if (setpgid(0, 0) != 0) {
51*5a923131SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to setpgid on subprocess " << getpid();
52*5a923131SAndroid Build Coastguard Worker     return false;
53*5a923131SAndroid Build Coastguard Worker   }
54*5a923131SAndroid Build Coastguard Worker   for (const auto& key_value : env) {
55*5a923131SAndroid Build Coastguard Worker     setenv(key_value.first.c_str(), key_value.second.c_str(), 0);
56*5a923131SAndroid Build Coastguard Worker   }
57*5a923131SAndroid Build Coastguard Worker 
58*5a923131SAndroid Build Coastguard Worker   if ((flags & Subprocess::kRedirectStderrToStdout) != 0) {
59*5a923131SAndroid Build Coastguard Worker     if (HANDLE_EINTR(dup2(STDOUT_FILENO, STDERR_FILENO)) != STDERR_FILENO)
60*5a923131SAndroid Build Coastguard Worker       return false;
61*5a923131SAndroid Build Coastguard Worker   }
62*5a923131SAndroid Build Coastguard Worker 
63*5a923131SAndroid Build Coastguard Worker   int fd = HANDLE_EINTR(open("/dev/null", O_RDONLY));
64*5a923131SAndroid Build Coastguard Worker   if (fd < 0)
65*5a923131SAndroid Build Coastguard Worker     return false;
66*5a923131SAndroid Build Coastguard Worker   if (HANDLE_EINTR(dup2(fd, STDIN_FILENO)) != STDIN_FILENO)
67*5a923131SAndroid Build Coastguard Worker     return false;
68*5a923131SAndroid Build Coastguard Worker   IGNORE_EINTR(close(fd));
69*5a923131SAndroid Build Coastguard Worker 
70*5a923131SAndroid Build Coastguard Worker   return true;
71*5a923131SAndroid Build Coastguard Worker }
72*5a923131SAndroid Build Coastguard Worker 
73*5a923131SAndroid Build Coastguard Worker // Helper function to launch a process with the given Subprocess::Flags.
74*5a923131SAndroid Build Coastguard Worker // This function only sets up and starts the process according to the |flags|.
75*5a923131SAndroid Build Coastguard Worker // The caller is responsible for watching the termination of the subprocess.
76*5a923131SAndroid Build Coastguard Worker // Return whether the process was successfully launched and fills in the |proc|
77*5a923131SAndroid Build Coastguard Worker // Process.
LaunchProcess(const vector<string> & cmd,uint32_t flags,const vector<int> & output_pipes,brillo::Process * proc)78*5a923131SAndroid Build Coastguard Worker bool LaunchProcess(const vector<string>& cmd,
79*5a923131SAndroid Build Coastguard Worker                    uint32_t flags,
80*5a923131SAndroid Build Coastguard Worker                    const vector<int>& output_pipes,
81*5a923131SAndroid Build Coastguard Worker                    brillo::Process* proc) {
82*5a923131SAndroid Build Coastguard Worker   for (const string& arg : cmd)
83*5a923131SAndroid Build Coastguard Worker     proc->AddArg(arg);
84*5a923131SAndroid Build Coastguard Worker   proc->SetSearchPath((flags & Subprocess::kSearchPath) != 0);
85*5a923131SAndroid Build Coastguard Worker 
86*5a923131SAndroid Build Coastguard Worker   // Create an environment for the child process with just the required PATHs.
87*5a923131SAndroid Build Coastguard Worker   std::map<string, string> env;
88*5a923131SAndroid Build Coastguard Worker   for (const char* key : {"LD_LIBRARY_PATH", "PATH"}) {
89*5a923131SAndroid Build Coastguard Worker     const char* value = getenv(key);
90*5a923131SAndroid Build Coastguard Worker     if (value)
91*5a923131SAndroid Build Coastguard Worker       env.emplace(key, value);
92*5a923131SAndroid Build Coastguard Worker   }
93*5a923131SAndroid Build Coastguard Worker 
94*5a923131SAndroid Build Coastguard Worker   for (const int fd : output_pipes) {
95*5a923131SAndroid Build Coastguard Worker     proc->RedirectUsingPipe(fd, false);
96*5a923131SAndroid Build Coastguard Worker   }
97*5a923131SAndroid Build Coastguard Worker   proc->SetCloseUnusedFileDescriptors(true);
98*5a923131SAndroid Build Coastguard Worker   proc->RedirectUsingPipe(STDOUT_FILENO, false);
99*5a923131SAndroid Build Coastguard Worker   proc->SetPreExecCallback(base::Bind(&SetupChild, env, flags));
100*5a923131SAndroid Build Coastguard Worker 
101*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Running \"" << android::base::Join(cmd, " ") << "\"";
102*5a923131SAndroid Build Coastguard Worker   return proc->Start();
103*5a923131SAndroid Build Coastguard Worker }
104*5a923131SAndroid Build Coastguard Worker 
105*5a923131SAndroid Build Coastguard Worker }  // namespace
106*5a923131SAndroid Build Coastguard Worker 
Init(brillo::AsynchronousSignalHandlerInterface * async_signal_handler)107*5a923131SAndroid Build Coastguard Worker void Subprocess::Init(
108*5a923131SAndroid Build Coastguard Worker     brillo::AsynchronousSignalHandlerInterface* async_signal_handler) {
109*5a923131SAndroid Build Coastguard Worker   if (subprocess_singleton_ == this)
110*5a923131SAndroid Build Coastguard Worker     return;
111*5a923131SAndroid Build Coastguard Worker   CHECK(subprocess_singleton_ == nullptr);
112*5a923131SAndroid Build Coastguard Worker   subprocess_singleton_ = this;
113*5a923131SAndroid Build Coastguard Worker 
114*5a923131SAndroid Build Coastguard Worker   process_reaper_.Register(async_signal_handler);
115*5a923131SAndroid Build Coastguard Worker }
116*5a923131SAndroid Build Coastguard Worker 
~Subprocess()117*5a923131SAndroid Build Coastguard Worker Subprocess::~Subprocess() {
118*5a923131SAndroid Build Coastguard Worker   if (subprocess_singleton_ == this)
119*5a923131SAndroid Build Coastguard Worker     subprocess_singleton_ = nullptr;
120*5a923131SAndroid Build Coastguard Worker }
121*5a923131SAndroid Build Coastguard Worker 
OnStdoutReady(SubprocessRecord * record)122*5a923131SAndroid Build Coastguard Worker void Subprocess::OnStdoutReady(SubprocessRecord* record) {
123*5a923131SAndroid Build Coastguard Worker   char buf[1024];
124*5a923131SAndroid Build Coastguard Worker   size_t bytes_read;
125*5a923131SAndroid Build Coastguard Worker   do {
126*5a923131SAndroid Build Coastguard Worker     bytes_read = 0;
127*5a923131SAndroid Build Coastguard Worker     bool eof;
128*5a923131SAndroid Build Coastguard Worker     bool ok = utils::ReadAll(
129*5a923131SAndroid Build Coastguard Worker         record->stdout_fd, buf, std::size(buf), &bytes_read, &eof);
130*5a923131SAndroid Build Coastguard Worker     record->stdout_str.append(buf, bytes_read);
131*5a923131SAndroid Build Coastguard Worker     if (!ok || eof) {
132*5a923131SAndroid Build Coastguard Worker       // There was either an error or an EOF condition, so we are done watching
133*5a923131SAndroid Build Coastguard Worker       // the file descriptor.
134*5a923131SAndroid Build Coastguard Worker       record->stdout_controller.reset();
135*5a923131SAndroid Build Coastguard Worker       return;
136*5a923131SAndroid Build Coastguard Worker     }
137*5a923131SAndroid Build Coastguard Worker   } while (bytes_read);
138*5a923131SAndroid Build Coastguard Worker }
139*5a923131SAndroid Build Coastguard Worker 
ChildExitedCallback(const siginfo_t & info)140*5a923131SAndroid Build Coastguard Worker void Subprocess::ChildExitedCallback(const siginfo_t& info) {
141*5a923131SAndroid Build Coastguard Worker   auto pid_record = subprocess_records_.find(info.si_pid);
142*5a923131SAndroid Build Coastguard Worker   if (pid_record == subprocess_records_.end())
143*5a923131SAndroid Build Coastguard Worker     return;
144*5a923131SAndroid Build Coastguard Worker   SubprocessRecord* record = pid_record->second.get();
145*5a923131SAndroid Build Coastguard Worker 
146*5a923131SAndroid Build Coastguard Worker   // Make sure we read any remaining process output and then close the pipe.
147*5a923131SAndroid Build Coastguard Worker   OnStdoutReady(record);
148*5a923131SAndroid Build Coastguard Worker 
149*5a923131SAndroid Build Coastguard Worker   record->stdout_controller.reset();
150*5a923131SAndroid Build Coastguard Worker 
151*5a923131SAndroid Build Coastguard Worker   // Don't print any log if the subprocess exited with exit code 0.
152*5a923131SAndroid Build Coastguard Worker   if (info.si_code != CLD_EXITED) {
153*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Subprocess " << info.si_pid << " terminated with si_code "
154*5a923131SAndroid Build Coastguard Worker               << info.si_code;
155*5a923131SAndroid Build Coastguard Worker   } else if (info.si_status != 0) {
156*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Subprocess " << info.si_pid
157*5a923131SAndroid Build Coastguard Worker               << " exited with si_status: " << info.si_status;
158*5a923131SAndroid Build Coastguard Worker   }
159*5a923131SAndroid Build Coastguard Worker 
160*5a923131SAndroid Build Coastguard Worker   if (!record->stdout_str.empty()) {
161*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Subprocess output:\n" << record->stdout_str;
162*5a923131SAndroid Build Coastguard Worker   }
163*5a923131SAndroid Build Coastguard Worker   if (!record->callback.is_null()) {
164*5a923131SAndroid Build Coastguard Worker     record->callback.Run(info.si_status, record->stdout_str);
165*5a923131SAndroid Build Coastguard Worker   }
166*5a923131SAndroid Build Coastguard Worker   // Release and close all the pipes after calling the callback so our
167*5a923131SAndroid Build Coastguard Worker   // redirected pipes are still alive. Releasing the process first makes
168*5a923131SAndroid Build Coastguard Worker   // Reset(0) not attempt to kill the process, which is already a zombie at this
169*5a923131SAndroid Build Coastguard Worker   // point.
170*5a923131SAndroid Build Coastguard Worker   record->proc.Release();
171*5a923131SAndroid Build Coastguard Worker   record->proc.Reset(0);
172*5a923131SAndroid Build Coastguard Worker 
173*5a923131SAndroid Build Coastguard Worker   subprocess_records_.erase(pid_record);
174*5a923131SAndroid Build Coastguard Worker }
175*5a923131SAndroid Build Coastguard Worker 
Exec(const vector<string> & cmd,const ExecCallback & callback)176*5a923131SAndroid Build Coastguard Worker pid_t Subprocess::Exec(const vector<string>& cmd,
177*5a923131SAndroid Build Coastguard Worker                        const ExecCallback& callback) {
178*5a923131SAndroid Build Coastguard Worker   return ExecFlags(cmd, kRedirectStderrToStdout, {}, callback);
179*5a923131SAndroid Build Coastguard Worker }
180*5a923131SAndroid Build Coastguard Worker 
ExecFlags(const vector<string> & cmd,uint32_t flags,const vector<int> & output_pipes,const ExecCallback & callback)181*5a923131SAndroid Build Coastguard Worker pid_t Subprocess::ExecFlags(const vector<string>& cmd,
182*5a923131SAndroid Build Coastguard Worker                             uint32_t flags,
183*5a923131SAndroid Build Coastguard Worker                             const vector<int>& output_pipes,
184*5a923131SAndroid Build Coastguard Worker                             const ExecCallback& callback) {
185*5a923131SAndroid Build Coastguard Worker   unique_ptr<SubprocessRecord> record(new SubprocessRecord(callback));
186*5a923131SAndroid Build Coastguard Worker 
187*5a923131SAndroid Build Coastguard Worker   if (!LaunchProcess(cmd, flags, output_pipes, &record->proc)) {
188*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to launch subprocess";
189*5a923131SAndroid Build Coastguard Worker     return 0;
190*5a923131SAndroid Build Coastguard Worker   }
191*5a923131SAndroid Build Coastguard Worker 
192*5a923131SAndroid Build Coastguard Worker   pid_t pid = record->proc.pid();
193*5a923131SAndroid Build Coastguard Worker   CHECK(process_reaper_.WatchForChild(
194*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
195*5a923131SAndroid Build Coastguard Worker       pid,
196*5a923131SAndroid Build Coastguard Worker       base::Bind(&Subprocess::ChildExitedCallback, base::Unretained(this))));
197*5a923131SAndroid Build Coastguard Worker 
198*5a923131SAndroid Build Coastguard Worker   record->stdout_fd = record->proc.GetPipe(STDOUT_FILENO);
199*5a923131SAndroid Build Coastguard Worker   // Capture the subprocess output. Make our end of the pipe non-blocking.
200*5a923131SAndroid Build Coastguard Worker   int fd_flags = fcntl(record->stdout_fd, F_GETFL, 0) | O_NONBLOCK;
201*5a923131SAndroid Build Coastguard Worker   if (HANDLE_EINTR(fcntl(record->stdout_fd, F_SETFL, fd_flags)) < 0) {
202*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to set non-blocking I/O mode on fd "
203*5a923131SAndroid Build Coastguard Worker                << record->stdout_fd << ".";
204*5a923131SAndroid Build Coastguard Worker   }
205*5a923131SAndroid Build Coastguard Worker 
206*5a923131SAndroid Build Coastguard Worker   record->stdout_controller = base::FileDescriptorWatcher::WatchReadable(
207*5a923131SAndroid Build Coastguard Worker       record->stdout_fd,
208*5a923131SAndroid Build Coastguard Worker       base::BindRepeating(&Subprocess::OnStdoutReady, record.get()));
209*5a923131SAndroid Build Coastguard Worker 
210*5a923131SAndroid Build Coastguard Worker   subprocess_records_[pid] = std::move(record);
211*5a923131SAndroid Build Coastguard Worker   return pid;
212*5a923131SAndroid Build Coastguard Worker }
213*5a923131SAndroid Build Coastguard Worker 
WaitForProcessGroup(pid_t pid,std::chrono::milliseconds timeout)214*5a923131SAndroid Build Coastguard Worker bool WaitForProcessGroup(pid_t pid, std::chrono::milliseconds timeout) {
215*5a923131SAndroid Build Coastguard Worker   using std::chrono::system_clock;
216*5a923131SAndroid Build Coastguard Worker   auto start = system_clock::now();
217*5a923131SAndroid Build Coastguard Worker   do {
218*5a923131SAndroid Build Coastguard Worker     pid_t w = waitpid(-pid, nullptr, WNOHANG);
219*5a923131SAndroid Build Coastguard Worker     if (w < 0) {
220*5a923131SAndroid Build Coastguard Worker       // When all of the child process with this process group ID exits, waitpid
221*5a923131SAndroid Build Coastguard Worker       // will return ECHILD. Until that point, keep callilng waitpid() as there
222*5a923131SAndroid Build Coastguard Worker       // might be multiple child processes with the same process group id.
223*5a923131SAndroid Build Coastguard Worker       if (errno == ECHILD) {
224*5a923131SAndroid Build Coastguard Worker         LOG(INFO) << "All processes with process group id " << pid << " exited";
225*5a923131SAndroid Build Coastguard Worker         return true;
226*5a923131SAndroid Build Coastguard Worker       }
227*5a923131SAndroid Build Coastguard Worker       PLOG(ERROR) << "Waitpid returned " << w;
228*5a923131SAndroid Build Coastguard Worker       return false;
229*5a923131SAndroid Build Coastguard Worker     }
230*5a923131SAndroid Build Coastguard Worker     usleep(100);
231*5a923131SAndroid Build Coastguard Worker   } while ((system_clock::now() - start) <= timeout);
232*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "process group " << pid << " did not exit in " << timeout.count()
233*5a923131SAndroid Build Coastguard Worker             << " milliseconds";
234*5a923131SAndroid Build Coastguard Worker   return false;
235*5a923131SAndroid Build Coastguard Worker }
236*5a923131SAndroid Build Coastguard Worker 
KillExec(pid_t pid)237*5a923131SAndroid Build Coastguard Worker void Subprocess::KillExec(pid_t pid) {
238*5a923131SAndroid Build Coastguard Worker   using namespace std::chrono_literals;
239*5a923131SAndroid Build Coastguard Worker   auto pid_record = subprocess_records_.find(pid);
240*5a923131SAndroid Build Coastguard Worker   if (pid_record == subprocess_records_.end())
241*5a923131SAndroid Build Coastguard Worker     return;
242*5a923131SAndroid Build Coastguard Worker   pid_record->second->callback.Reset();
243*5a923131SAndroid Build Coastguard Worker   // We don't care about output/return code, so we use SIGKILL here to ensure it
244*5a923131SAndroid Build Coastguard Worker   // will be killed, SIGTERM might lead to leaked subprocess.
245*5a923131SAndroid Build Coastguard Worker   CHECK_EQ(pid_record->second->proc.pid(), pid);
246*5a923131SAndroid Build Coastguard Worker   if (kill(-pid, SIGKILL) != 0) {
247*5a923131SAndroid Build Coastguard Worker     PLOG(WARNING) << "Failed to kill subprocess group " << pid;
248*5a923131SAndroid Build Coastguard Worker   }
249*5a923131SAndroid Build Coastguard Worker   WaitForProcessGroup(pid, 5000ms);
250*5a923131SAndroid Build Coastguard Worker   // Release the pid now so we don't try to kill it if Subprocess is destroyed
251*5a923131SAndroid Build Coastguard Worker   // before the corresponding ChildExitedCallback() is called.
252*5a923131SAndroid Build Coastguard Worker   pid_record->second->proc.Release();
253*5a923131SAndroid Build Coastguard Worker   if (subprocess_records_.count(pid)) {
254*5a923131SAndroid Build Coastguard Worker     siginfo_t info;
255*5a923131SAndroid Build Coastguard Worker     info.si_code = CLD_KILLED;
256*5a923131SAndroid Build Coastguard Worker     info.si_status = SIGKILL;
257*5a923131SAndroid Build Coastguard Worker     info.si_pid = pid;
258*5a923131SAndroid Build Coastguard Worker     ChildExitedCallback(info);
259*5a923131SAndroid Build Coastguard Worker   }
260*5a923131SAndroid Build Coastguard Worker }
261*5a923131SAndroid Build Coastguard Worker 
GetPipeFd(pid_t pid,int fd) const262*5a923131SAndroid Build Coastguard Worker int Subprocess::GetPipeFd(pid_t pid, int fd) const {
263*5a923131SAndroid Build Coastguard Worker   auto pid_record = subprocess_records_.find(pid);
264*5a923131SAndroid Build Coastguard Worker   if (pid_record == subprocess_records_.end())
265*5a923131SAndroid Build Coastguard Worker     return -1;
266*5a923131SAndroid Build Coastguard Worker   return pid_record->second->proc.GetPipe(fd);
267*5a923131SAndroid Build Coastguard Worker }
268*5a923131SAndroid Build Coastguard Worker 
SynchronousExec(const vector<string> & cmd,int * return_code,string * stdout_str,string * stderr_str)269*5a923131SAndroid Build Coastguard Worker bool Subprocess::SynchronousExec(const vector<string>& cmd,
270*5a923131SAndroid Build Coastguard Worker                                  int* return_code,
271*5a923131SAndroid Build Coastguard Worker                                  string* stdout_str,
272*5a923131SAndroid Build Coastguard Worker                                  string* stderr_str) {
273*5a923131SAndroid Build Coastguard Worker   // The default for |SynchronousExec| is to use |kSearchPath| since the code
274*5a923131SAndroid Build Coastguard Worker   // relies on that.
275*5a923131SAndroid Build Coastguard Worker   return SynchronousExecFlags(
276*5a923131SAndroid Build Coastguard Worker       cmd, kSearchPath, return_code, stdout_str, stderr_str);
277*5a923131SAndroid Build Coastguard Worker }
278*5a923131SAndroid Build Coastguard Worker 
SynchronousExecFlags(const vector<string> & cmd,uint32_t flags,int * return_code,string * stdout_str,string * stderr_str)279*5a923131SAndroid Build Coastguard Worker bool Subprocess::SynchronousExecFlags(const vector<string>& cmd,
280*5a923131SAndroid Build Coastguard Worker                                       uint32_t flags,
281*5a923131SAndroid Build Coastguard Worker                                       int* return_code,
282*5a923131SAndroid Build Coastguard Worker                                       string* stdout_str,
283*5a923131SAndroid Build Coastguard Worker                                       string* stderr_str) {
284*5a923131SAndroid Build Coastguard Worker   brillo::ProcessImpl proc;
285*5a923131SAndroid Build Coastguard Worker   if (!LaunchProcess(cmd, flags, {STDERR_FILENO}, &proc)) {
286*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to launch subprocess";
287*5a923131SAndroid Build Coastguard Worker     return false;
288*5a923131SAndroid Build Coastguard Worker   }
289*5a923131SAndroid Build Coastguard Worker 
290*5a923131SAndroid Build Coastguard Worker   if (stdout_str) {
291*5a923131SAndroid Build Coastguard Worker     stdout_str->clear();
292*5a923131SAndroid Build Coastguard Worker   }
293*5a923131SAndroid Build Coastguard Worker   if (stderr_str) {
294*5a923131SAndroid Build Coastguard Worker     stderr_str->clear();
295*5a923131SAndroid Build Coastguard Worker   }
296*5a923131SAndroid Build Coastguard Worker 
297*5a923131SAndroid Build Coastguard Worker   // Read from both stdout and stderr individually.
298*5a923131SAndroid Build Coastguard Worker   int stdout_fd = proc.GetPipe(STDOUT_FILENO);
299*5a923131SAndroid Build Coastguard Worker   int stderr_fd = proc.GetPipe(STDERR_FILENO);
300*5a923131SAndroid Build Coastguard Worker   vector<char> buffer(32 * 1024);
301*5a923131SAndroid Build Coastguard Worker   bool stdout_closed = false, stderr_closed = false;
302*5a923131SAndroid Build Coastguard Worker   while (!stdout_closed || !stderr_closed) {
303*5a923131SAndroid Build Coastguard Worker     if (!stdout_closed) {
304*5a923131SAndroid Build Coastguard Worker       int rc = HANDLE_EINTR(read(stdout_fd, buffer.data(), buffer.size()));
305*5a923131SAndroid Build Coastguard Worker       if (rc <= 0) {
306*5a923131SAndroid Build Coastguard Worker         stdout_closed = true;
307*5a923131SAndroid Build Coastguard Worker         if (rc < 0)
308*5a923131SAndroid Build Coastguard Worker           PLOG(ERROR) << "Reading from child's stdout";
309*5a923131SAndroid Build Coastguard Worker       } else if (stdout_str != nullptr) {
310*5a923131SAndroid Build Coastguard Worker         stdout_str->append(buffer.data(), rc);
311*5a923131SAndroid Build Coastguard Worker       }
312*5a923131SAndroid Build Coastguard Worker     }
313*5a923131SAndroid Build Coastguard Worker 
314*5a923131SAndroid Build Coastguard Worker     if (!stderr_closed) {
315*5a923131SAndroid Build Coastguard Worker       int rc = HANDLE_EINTR(read(stderr_fd, buffer.data(), buffer.size()));
316*5a923131SAndroid Build Coastguard Worker       if (rc <= 0) {
317*5a923131SAndroid Build Coastguard Worker         stderr_closed = true;
318*5a923131SAndroid Build Coastguard Worker         if (rc < 0)
319*5a923131SAndroid Build Coastguard Worker           PLOG(ERROR) << "Reading from child's stderr";
320*5a923131SAndroid Build Coastguard Worker       } else if (stderr_str != nullptr) {
321*5a923131SAndroid Build Coastguard Worker         stderr_str->append(buffer.data(), rc);
322*5a923131SAndroid Build Coastguard Worker       }
323*5a923131SAndroid Build Coastguard Worker     }
324*5a923131SAndroid Build Coastguard Worker   }
325*5a923131SAndroid Build Coastguard Worker 
326*5a923131SAndroid Build Coastguard Worker   // At this point, the subprocess already closed the output, so we only need to
327*5a923131SAndroid Build Coastguard Worker   // wait for it to finish.
328*5a923131SAndroid Build Coastguard Worker   int proc_return_code = proc.Wait();
329*5a923131SAndroid Build Coastguard Worker   if (return_code)
330*5a923131SAndroid Build Coastguard Worker     *return_code = proc_return_code;
331*5a923131SAndroid Build Coastguard Worker   return proc_return_code != brillo::Process::kErrorExitStatus;
332*5a923131SAndroid Build Coastguard Worker }
333*5a923131SAndroid Build Coastguard Worker 
FlushBufferedLogsAtExit()334*5a923131SAndroid Build Coastguard Worker void Subprocess::FlushBufferedLogsAtExit() {
335*5a923131SAndroid Build Coastguard Worker   if (!subprocess_records_.empty()) {
336*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "We are exiting, but there are still in flight subprocesses!";
337*5a923131SAndroid Build Coastguard Worker     for (auto& pid_record : subprocess_records_) {
338*5a923131SAndroid Build Coastguard Worker       SubprocessRecord* record = pid_record.second.get();
339*5a923131SAndroid Build Coastguard Worker       // Make sure we read any remaining process output.
340*5a923131SAndroid Build Coastguard Worker       OnStdoutReady(record);
341*5a923131SAndroid Build Coastguard Worker       if (!record->stdout_str.empty()) {
342*5a923131SAndroid Build Coastguard Worker         LOG(INFO) << "Subprocess(" << pid_record.first << ") output:\n"
343*5a923131SAndroid Build Coastguard Worker                   << record->stdout_str;
344*5a923131SAndroid Build Coastguard Worker       }
345*5a923131SAndroid Build Coastguard Worker     }
346*5a923131SAndroid Build Coastguard Worker   }
347*5a923131SAndroid Build Coastguard Worker }
348*5a923131SAndroid Build Coastguard Worker 
349*5a923131SAndroid Build Coastguard Worker Subprocess* Subprocess::subprocess_singleton_ = nullptr;
350*5a923131SAndroid Build Coastguard Worker 
351*5a923131SAndroid Build Coastguard Worker }  // namespace chromeos_update_engine
352