• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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