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