xref: /aosp_15_r20/frameworks/native/libs/binder/UtilsHost.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2021 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #include "UtilsHost.h"
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <poll.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <string.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <sys/types.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <sys/wait.h>
23*38e8c45fSAndroid Build Coastguard Worker 
24*38e8c45fSAndroid Build Coastguard Worker #include <sstream>
25*38e8c45fSAndroid Build Coastguard Worker 
26*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
27*38e8c45fSAndroid Build Coastguard Worker 
28*38e8c45fSAndroid Build Coastguard Worker #include "FdUtils.h"
29*38e8c45fSAndroid Build Coastguard Worker #include "Utils.h"
30*38e8c45fSAndroid Build Coastguard Worker 
31*38e8c45fSAndroid Build Coastguard Worker namespace android {
32*38e8c45fSAndroid Build Coastguard Worker 
33*38e8c45fSAndroid Build Coastguard Worker using android::binder::unique_fd;
34*38e8c45fSAndroid Build Coastguard Worker 
~CommandResult()35*38e8c45fSAndroid Build Coastguard Worker CommandResult::~CommandResult() {
36*38e8c45fSAndroid Build Coastguard Worker     if (!pid.has_value()) return;
37*38e8c45fSAndroid Build Coastguard Worker     if (*pid == 0) {
38*38e8c45fSAndroid Build Coastguard Worker         ALOGW("%s: PID is unexpectedly 0, won't kill it", __PRETTY_FUNCTION__);
39*38e8c45fSAndroid Build Coastguard Worker         return;
40*38e8c45fSAndroid Build Coastguard Worker     }
41*38e8c45fSAndroid Build Coastguard Worker 
42*38e8c45fSAndroid Build Coastguard Worker     ALOGE_IF(kill(*pid, SIGKILL) != 0, "kill(%d): %s", *pid, strerror(errno));
43*38e8c45fSAndroid Build Coastguard Worker 
44*38e8c45fSAndroid Build Coastguard Worker     while (pid.has_value()) {
45*38e8c45fSAndroid Build Coastguard Worker         int status;
46*38e8c45fSAndroid Build Coastguard Worker         LOG_HOST("%s: Waiting for PID %d to exit.", __PRETTY_FUNCTION__, *pid);
47*38e8c45fSAndroid Build Coastguard Worker         int waitres = waitpid(*pid, &status, 0);
48*38e8c45fSAndroid Build Coastguard Worker         if (waitres == -1) {
49*38e8c45fSAndroid Build Coastguard Worker             ALOGE("%s: waitpid(%d): %s", __PRETTY_FUNCTION__, *pid, strerror(errno));
50*38e8c45fSAndroid Build Coastguard Worker             break;
51*38e8c45fSAndroid Build Coastguard Worker         }
52*38e8c45fSAndroid Build Coastguard Worker         if (WIFEXITED(status)) {
53*38e8c45fSAndroid Build Coastguard Worker             LOG_HOST("%s: PID %d exited.", __PRETTY_FUNCTION__, *pid);
54*38e8c45fSAndroid Build Coastguard Worker             pid.reset();
55*38e8c45fSAndroid Build Coastguard Worker         } else if (WIFSIGNALED(status)) {
56*38e8c45fSAndroid Build Coastguard Worker             LOG_HOST("%s: PID %d terminated by signal %d.", __PRETTY_FUNCTION__, *pid,
57*38e8c45fSAndroid Build Coastguard Worker                      WTERMSIG(status));
58*38e8c45fSAndroid Build Coastguard Worker             pid.reset();
59*38e8c45fSAndroid Build Coastguard Worker         } else if (WIFSTOPPED(status)) {
60*38e8c45fSAndroid Build Coastguard Worker             ALOGW("%s: pid %d stopped", __PRETTY_FUNCTION__, *pid);
61*38e8c45fSAndroid Build Coastguard Worker         } else if (WIFCONTINUED(status)) {
62*38e8c45fSAndroid Build Coastguard Worker             ALOGW("%s: pid %d continued", __PRETTY_FUNCTION__, *pid);
63*38e8c45fSAndroid Build Coastguard Worker         }
64*38e8c45fSAndroid Build Coastguard Worker     }
65*38e8c45fSAndroid Build Coastguard Worker }
66*38e8c45fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const CommandResult & res)67*38e8c45fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const CommandResult& res) {
68*38e8c45fSAndroid Build Coastguard Worker     if (res.exitCode) os << "code=" << *res.exitCode;
69*38e8c45fSAndroid Build Coastguard Worker     if (res.signal) os << "signal=" << *res.signal;
70*38e8c45fSAndroid Build Coastguard Worker     if (res.pid) os << ", pid=" << *res.pid;
71*38e8c45fSAndroid Build Coastguard Worker     return os << ", stdout=" << res.stdoutStr << ", stderr=" << res.stderrStr;
72*38e8c45fSAndroid Build Coastguard Worker }
73*38e8c45fSAndroid Build Coastguard Worker 
toString() const74*38e8c45fSAndroid Build Coastguard Worker std::string CommandResult::toString() const {
75*38e8c45fSAndroid Build Coastguard Worker     std::stringstream ss;
76*38e8c45fSAndroid Build Coastguard Worker     ss << (*this);
77*38e8c45fSAndroid Build Coastguard Worker     return ss.str();
78*38e8c45fSAndroid Build Coastguard Worker }
79*38e8c45fSAndroid Build Coastguard Worker 
execute(std::vector<std::string> argStringVec,const std::function<bool (const CommandResult &)> & end)80*38e8c45fSAndroid Build Coastguard Worker std::optional<CommandResult> execute(std::vector<std::string> argStringVec,
81*38e8c45fSAndroid Build Coastguard Worker                                      const std::function<bool(const CommandResult&)>& end) {
82*38e8c45fSAndroid Build Coastguard Worker     // turn vector<string> into null-terminated char* vector.
83*38e8c45fSAndroid Build Coastguard Worker     std::vector<char*> argv;
84*38e8c45fSAndroid Build Coastguard Worker     argv.reserve(argStringVec.size() + 1);
85*38e8c45fSAndroid Build Coastguard Worker     for (auto& arg : argStringVec) argv.push_back(arg.data());
86*38e8c45fSAndroid Build Coastguard Worker     argv.push_back(nullptr);
87*38e8c45fSAndroid Build Coastguard Worker 
88*38e8c45fSAndroid Build Coastguard Worker     CommandResult ret;
89*38e8c45fSAndroid Build Coastguard Worker     unique_fd outWrite;
90*38e8c45fSAndroid Build Coastguard Worker     if (!binder::Pipe(&ret.outPipe, &outWrite)) {
91*38e8c45fSAndroid Build Coastguard Worker         PLOGE("pipe() for outPipe");
92*38e8c45fSAndroid Build Coastguard Worker         return {};
93*38e8c45fSAndroid Build Coastguard Worker     }
94*38e8c45fSAndroid Build Coastguard Worker     unique_fd errWrite;
95*38e8c45fSAndroid Build Coastguard Worker     if (!binder::Pipe(&ret.errPipe, &errWrite)) {
96*38e8c45fSAndroid Build Coastguard Worker         PLOGE("pipe() for errPipe");
97*38e8c45fSAndroid Build Coastguard Worker         return {};
98*38e8c45fSAndroid Build Coastguard Worker     }
99*38e8c45fSAndroid Build Coastguard Worker 
100*38e8c45fSAndroid Build Coastguard Worker     int pid = fork();
101*38e8c45fSAndroid Build Coastguard Worker     if (pid == -1) {
102*38e8c45fSAndroid Build Coastguard Worker         PLOGE("fork()");
103*38e8c45fSAndroid Build Coastguard Worker         return {};
104*38e8c45fSAndroid Build Coastguard Worker     }
105*38e8c45fSAndroid Build Coastguard Worker     if (pid == 0) {
106*38e8c45fSAndroid Build Coastguard Worker         // child
107*38e8c45fSAndroid Build Coastguard Worker         ret.outPipe.reset();
108*38e8c45fSAndroid Build Coastguard Worker         ret.errPipe.reset();
109*38e8c45fSAndroid Build Coastguard Worker 
110*38e8c45fSAndroid Build Coastguard Worker         int res = TEMP_FAILURE_RETRY(dup2(outWrite.get(), STDOUT_FILENO));
111*38e8c45fSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(-1 == res, "dup2(outPipe): %s", strerror(errno));
112*38e8c45fSAndroid Build Coastguard Worker         outWrite.reset();
113*38e8c45fSAndroid Build Coastguard Worker 
114*38e8c45fSAndroid Build Coastguard Worker         res = TEMP_FAILURE_RETRY(dup2(errWrite.get(), STDERR_FILENO));
115*38e8c45fSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(-1 == res, "dup2(errPipe): %s", strerror(errno));
116*38e8c45fSAndroid Build Coastguard Worker         errWrite.reset();
117*38e8c45fSAndroid Build Coastguard Worker 
118*38e8c45fSAndroid Build Coastguard Worker         execvp(argv[0], argv.data());
119*38e8c45fSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL("execvp() returns");
120*38e8c45fSAndroid Build Coastguard Worker     }
121*38e8c45fSAndroid Build Coastguard Worker     // parent
122*38e8c45fSAndroid Build Coastguard Worker     outWrite.reset();
123*38e8c45fSAndroid Build Coastguard Worker     errWrite.reset();
124*38e8c45fSAndroid Build Coastguard Worker     ret.pid = pid;
125*38e8c45fSAndroid Build Coastguard Worker 
126*38e8c45fSAndroid Build Coastguard Worker     auto handlePoll = [](unique_fd* fd, const pollfd* pfd, std::string* s) {
127*38e8c45fSAndroid Build Coastguard Worker         if (!fd->ok()) return true;
128*38e8c45fSAndroid Build Coastguard Worker         if (pfd->revents & POLLIN) {
129*38e8c45fSAndroid Build Coastguard Worker             char buf[1024];
130*38e8c45fSAndroid Build Coastguard Worker             ssize_t n = TEMP_FAILURE_RETRY(read(fd->get(), buf, sizeof(buf)));
131*38e8c45fSAndroid Build Coastguard Worker             if (n < 0) return false;
132*38e8c45fSAndroid Build Coastguard Worker             if (n > 0) *s += std::string_view(buf, n);
133*38e8c45fSAndroid Build Coastguard Worker         }
134*38e8c45fSAndroid Build Coastguard Worker         if (pfd->revents & POLLHUP) {
135*38e8c45fSAndroid Build Coastguard Worker             fd->reset();
136*38e8c45fSAndroid Build Coastguard Worker         }
137*38e8c45fSAndroid Build Coastguard Worker         return true;
138*38e8c45fSAndroid Build Coastguard Worker     };
139*38e8c45fSAndroid Build Coastguard Worker 
140*38e8c45fSAndroid Build Coastguard Worker     // Drain both stdout and stderr. Check end() regularly until both are closed.
141*38e8c45fSAndroid Build Coastguard Worker     while (ret.outPipe.ok() || ret.errPipe.ok()) {
142*38e8c45fSAndroid Build Coastguard Worker         pollfd fds[2];
143*38e8c45fSAndroid Build Coastguard Worker         pollfd *outPollFd = nullptr, *errPollFd = nullptr;
144*38e8c45fSAndroid Build Coastguard Worker         memset(fds, 0, sizeof(fds));
145*38e8c45fSAndroid Build Coastguard Worker         nfds_t nfds = 0;
146*38e8c45fSAndroid Build Coastguard Worker         if (ret.outPipe.ok()) {
147*38e8c45fSAndroid Build Coastguard Worker             outPollFd = &fds[nfds++];
148*38e8c45fSAndroid Build Coastguard Worker             *outPollFd = {.fd = ret.outPipe.get(), .events = POLLIN};
149*38e8c45fSAndroid Build Coastguard Worker         }
150*38e8c45fSAndroid Build Coastguard Worker         if (ret.errPipe.ok()) {
151*38e8c45fSAndroid Build Coastguard Worker             errPollFd = &fds[nfds++];
152*38e8c45fSAndroid Build Coastguard Worker             *errPollFd = {.fd = ret.errPipe.get(), .events = POLLIN};
153*38e8c45fSAndroid Build Coastguard Worker         }
154*38e8c45fSAndroid Build Coastguard Worker         int pollRet = poll(fds, nfds, 1000 /* ms timeout */);
155*38e8c45fSAndroid Build Coastguard Worker         if (pollRet == -1) {
156*38e8c45fSAndroid Build Coastguard Worker             PLOGE("poll()");
157*38e8c45fSAndroid Build Coastguard Worker             return {};
158*38e8c45fSAndroid Build Coastguard Worker         }
159*38e8c45fSAndroid Build Coastguard Worker 
160*38e8c45fSAndroid Build Coastguard Worker         if (!handlePoll(&ret.outPipe, outPollFd, &ret.stdoutStr)) {
161*38e8c45fSAndroid Build Coastguard Worker             PLOGE("read(stdout)");
162*38e8c45fSAndroid Build Coastguard Worker             return {};
163*38e8c45fSAndroid Build Coastguard Worker         }
164*38e8c45fSAndroid Build Coastguard Worker         if (!handlePoll(&ret.errPipe, errPollFd, &ret.stderrStr)) {
165*38e8c45fSAndroid Build Coastguard Worker             PLOGE("read(stderr)");
166*38e8c45fSAndroid Build Coastguard Worker             return {};
167*38e8c45fSAndroid Build Coastguard Worker         }
168*38e8c45fSAndroid Build Coastguard Worker 
169*38e8c45fSAndroid Build Coastguard Worker         if (end && end(ret)) return ret;
170*38e8c45fSAndroid Build Coastguard Worker     }
171*38e8c45fSAndroid Build Coastguard Worker 
172*38e8c45fSAndroid Build Coastguard Worker     // If both stdout and stderr are closed by the subprocess, it may or may not be terminated.
173*38e8c45fSAndroid Build Coastguard Worker     while (ret.pid.has_value()) {
174*38e8c45fSAndroid Build Coastguard Worker         int status;
175*38e8c45fSAndroid Build Coastguard Worker         auto exitPid = waitpid(pid, &status, 0);
176*38e8c45fSAndroid Build Coastguard Worker         if (exitPid == -1) {
177*38e8c45fSAndroid Build Coastguard Worker             PLOGE("waitpid(%d)", pid);
178*38e8c45fSAndroid Build Coastguard Worker             return {};
179*38e8c45fSAndroid Build Coastguard Worker         }
180*38e8c45fSAndroid Build Coastguard Worker         if (exitPid == pid) {
181*38e8c45fSAndroid Build Coastguard Worker             if (WIFEXITED(status)) {
182*38e8c45fSAndroid Build Coastguard Worker                 ret.pid = std::nullopt;
183*38e8c45fSAndroid Build Coastguard Worker                 ret.exitCode = WEXITSTATUS(status);
184*38e8c45fSAndroid Build Coastguard Worker             } else if (WIFSIGNALED(status)) {
185*38e8c45fSAndroid Build Coastguard Worker                 ret.pid = std::nullopt;
186*38e8c45fSAndroid Build Coastguard Worker                 ret.signal = WTERMSIG(status);
187*38e8c45fSAndroid Build Coastguard Worker             } else if (WIFSTOPPED(status)) {
188*38e8c45fSAndroid Build Coastguard Worker                 ALOGW("%s: pid %d stopped", __PRETTY_FUNCTION__, *ret.pid);
189*38e8c45fSAndroid Build Coastguard Worker             } else if (WIFCONTINUED(status)) {
190*38e8c45fSAndroid Build Coastguard Worker                 ALOGW("%s: pid %d continued", __PRETTY_FUNCTION__, *ret.pid);
191*38e8c45fSAndroid Build Coastguard Worker             }
192*38e8c45fSAndroid Build Coastguard Worker         }
193*38e8c45fSAndroid Build Coastguard Worker         // ret is not changed unless the process is terminated (where pid == nullopt). Hence there
194*38e8c45fSAndroid Build Coastguard Worker         // is no need to check the predicate `end(ret)`.
195*38e8c45fSAndroid Build Coastguard Worker     }
196*38e8c45fSAndroid Build Coastguard Worker 
197*38e8c45fSAndroid Build Coastguard Worker     return ret;
198*38e8c45fSAndroid Build Coastguard Worker }
199*38e8c45fSAndroid Build Coastguard Worker } // namespace android
200