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