1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "tools/tools.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <errno.h>
20*795d594fSAndroid Build Coastguard Worker #include <fnmatch.h>
21*795d594fSAndroid Build Coastguard Worker #include <poll.h>
22*795d594fSAndroid Build Coastguard Worker #include <signal.h>
23*795d594fSAndroid Build Coastguard Worker #include <stdio.h>
24*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Worker #include <algorithm>
27*795d594fSAndroid Build Coastguard Worker #include <cstdint>
28*795d594fSAndroid Build Coastguard Worker #include <ctime>
29*795d594fSAndroid Build Coastguard Worker #include <filesystem>
30*795d594fSAndroid Build Coastguard Worker #include <functional>
31*795d594fSAndroid Build Coastguard Worker #include <regex>
32*795d594fSAndroid Build Coastguard Worker #include <string>
33*795d594fSAndroid Build Coastguard Worker #include <string_view>
34*795d594fSAndroid Build Coastguard Worker #include <system_error>
35*795d594fSAndroid Build Coastguard Worker #include <unordered_map>
36*795d594fSAndroid Build Coastguard Worker #include <utility>
37*795d594fSAndroid Build Coastguard Worker #include <vector>
38*795d594fSAndroid Build Coastguard Worker
39*795d594fSAndroid Build Coastguard Worker #include "android-base/errors.h"
40*795d594fSAndroid Build Coastguard Worker #include "android-base/file.h"
41*795d594fSAndroid Build Coastguard Worker #include "android-base/function_ref.h"
42*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
43*795d594fSAndroid Build Coastguard Worker #include "android-base/process.h"
44*795d594fSAndroid Build Coastguard Worker #include "android-base/result.h"
45*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
46*795d594fSAndroid Build Coastguard Worker #include "android-base/unique_fd.h"
47*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
48*795d594fSAndroid Build Coastguard Worker #include "base/pidfd.h"
49*795d594fSAndroid Build Coastguard Worker #include "fstab/fstab.h"
50*795d594fSAndroid Build Coastguard Worker
51*795d594fSAndroid Build Coastguard Worker namespace art {
52*795d594fSAndroid Build Coastguard Worker namespace tools {
53*795d594fSAndroid Build Coastguard Worker
54*795d594fSAndroid Build Coastguard Worker namespace {
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker using ::android::base::AllPids;
57*795d594fSAndroid Build Coastguard Worker using ::android::base::ConsumeSuffix;
58*795d594fSAndroid Build Coastguard Worker using ::android::base::function_ref;
59*795d594fSAndroid Build Coastguard Worker using ::android::base::ReadFileToString;
60*795d594fSAndroid Build Coastguard Worker using ::android::base::Readlink;
61*795d594fSAndroid Build Coastguard Worker using ::android::base::Result;
62*795d594fSAndroid Build Coastguard Worker using ::android::base::unique_fd;
63*795d594fSAndroid Build Coastguard Worker using ::android::fs_mgr::Fstab;
64*795d594fSAndroid Build Coastguard Worker using ::android::fs_mgr::FstabEntry;
65*795d594fSAndroid Build Coastguard Worker using ::android::fs_mgr::ReadFstabFromProcMounts;
66*795d594fSAndroid Build Coastguard Worker using ::std::placeholders::_1;
67*795d594fSAndroid Build Coastguard Worker
MilliTime()68*795d594fSAndroid Build Coastguard Worker uint64_t MilliTime() {
69*795d594fSAndroid Build Coastguard Worker timespec now;
70*795d594fSAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &now);
71*795d594fSAndroid Build Coastguard Worker return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_nsec / UINT64_C(1000000);
72*795d594fSAndroid Build Coastguard Worker }
73*795d594fSAndroid Build Coastguard Worker
74*795d594fSAndroid Build Coastguard Worker // Returns true if `path_prefix` matches `pattern` or can be a prefix of a path that matches
75*795d594fSAndroid Build Coastguard Worker // `pattern` (i.e., `path_prefix` represents a directory that may contain a file whose path matches
76*795d594fSAndroid Build Coastguard Worker // `pattern`).
PartialMatch(const std::filesystem::path & pattern,const std::filesystem::path & path_prefix)77*795d594fSAndroid Build Coastguard Worker bool PartialMatch(const std::filesystem::path& pattern, const std::filesystem::path& path_prefix) {
78*795d594fSAndroid Build Coastguard Worker for (std::filesystem::path::const_iterator pattern_it = pattern.begin(),
79*795d594fSAndroid Build Coastguard Worker path_prefix_it = path_prefix.begin();
80*795d594fSAndroid Build Coastguard Worker ; // NOLINT
81*795d594fSAndroid Build Coastguard Worker pattern_it++, path_prefix_it++) {
82*795d594fSAndroid Build Coastguard Worker if (path_prefix_it == path_prefix.end()) {
83*795d594fSAndroid Build Coastguard Worker return true;
84*795d594fSAndroid Build Coastguard Worker }
85*795d594fSAndroid Build Coastguard Worker if (pattern_it == pattern.end()) {
86*795d594fSAndroid Build Coastguard Worker return false;
87*795d594fSAndroid Build Coastguard Worker }
88*795d594fSAndroid Build Coastguard Worker if (*pattern_it == "**") {
89*795d594fSAndroid Build Coastguard Worker return true;
90*795d594fSAndroid Build Coastguard Worker }
91*795d594fSAndroid Build Coastguard Worker if (fnmatch(pattern_it->c_str(), path_prefix_it->c_str(), /*flags=*/0) != 0) {
92*795d594fSAndroid Build Coastguard Worker return false;
93*795d594fSAndroid Build Coastguard Worker }
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker }
96*795d594fSAndroid Build Coastguard Worker
FullMatchRecursive(const std::filesystem::path & pattern,std::filesystem::path::const_iterator pattern_it,const std::filesystem::path & path,std::filesystem::path::const_iterator path_it,bool double_asterisk_visited=false)97*795d594fSAndroid Build Coastguard Worker bool FullMatchRecursive(const std::filesystem::path& pattern,
98*795d594fSAndroid Build Coastguard Worker std::filesystem::path::const_iterator pattern_it,
99*795d594fSAndroid Build Coastguard Worker const std::filesystem::path& path,
100*795d594fSAndroid Build Coastguard Worker std::filesystem::path::const_iterator path_it,
101*795d594fSAndroid Build Coastguard Worker bool double_asterisk_visited = false) {
102*795d594fSAndroid Build Coastguard Worker if (pattern_it == pattern.end() && path_it == path.end()) {
103*795d594fSAndroid Build Coastguard Worker return true;
104*795d594fSAndroid Build Coastguard Worker }
105*795d594fSAndroid Build Coastguard Worker if (pattern_it == pattern.end()) {
106*795d594fSAndroid Build Coastguard Worker return false;
107*795d594fSAndroid Build Coastguard Worker }
108*795d594fSAndroid Build Coastguard Worker if (*pattern_it == "**") {
109*795d594fSAndroid Build Coastguard Worker DCHECK(!double_asterisk_visited);
110*795d594fSAndroid Build Coastguard Worker std::filesystem::path::const_iterator next_pattern_it = pattern_it;
111*795d594fSAndroid Build Coastguard Worker return FullMatchRecursive(
112*795d594fSAndroid Build Coastguard Worker pattern, ++next_pattern_it, path, path_it, /*double_asterisk_visited=*/true) ||
113*795d594fSAndroid Build Coastguard Worker (path_it != path.end() && FullMatchRecursive(pattern, pattern_it, path, ++path_it));
114*795d594fSAndroid Build Coastguard Worker }
115*795d594fSAndroid Build Coastguard Worker if (path_it == path.end()) {
116*795d594fSAndroid Build Coastguard Worker return false;
117*795d594fSAndroid Build Coastguard Worker }
118*795d594fSAndroid Build Coastguard Worker if (fnmatch(pattern_it->c_str(), path_it->c_str(), /*flags=*/0) != 0) {
119*795d594fSAndroid Build Coastguard Worker return false;
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker return FullMatchRecursive(pattern, ++pattern_it, path, ++path_it);
122*795d594fSAndroid Build Coastguard Worker }
123*795d594fSAndroid Build Coastguard Worker
124*795d594fSAndroid Build Coastguard Worker // Returns true if `path` fully matches `pattern`.
FullMatch(const std::filesystem::path & pattern,const std::filesystem::path & path)125*795d594fSAndroid Build Coastguard Worker bool FullMatch(const std::filesystem::path& pattern, const std::filesystem::path& path) {
126*795d594fSAndroid Build Coastguard Worker return FullMatchRecursive(pattern, pattern.begin(), path, path.begin());
127*795d594fSAndroid Build Coastguard Worker }
128*795d594fSAndroid Build Coastguard Worker
MatchGlobRecursive(const std::vector<std::filesystem::path> & patterns,const std::filesystem::path & root_dir,std::vector<std::string> * results)129*795d594fSAndroid Build Coastguard Worker void MatchGlobRecursive(const std::vector<std::filesystem::path>& patterns,
130*795d594fSAndroid Build Coastguard Worker const std::filesystem::path& root_dir,
131*795d594fSAndroid Build Coastguard Worker /*out*/ std::vector<std::string>* results) {
132*795d594fSAndroid Build Coastguard Worker std::error_code ec;
133*795d594fSAndroid Build Coastguard Worker for (auto it = std::filesystem::recursive_directory_iterator(
134*795d594fSAndroid Build Coastguard Worker root_dir, std::filesystem::directory_options::skip_permission_denied, ec);
135*795d594fSAndroid Build Coastguard Worker !ec && it != std::filesystem::end(it);
136*795d594fSAndroid Build Coastguard Worker it.increment(ec)) {
137*795d594fSAndroid Build Coastguard Worker const std::filesystem::directory_entry& entry = *it;
138*795d594fSAndroid Build Coastguard Worker if (std::none_of(patterns.begin(), patterns.end(), std::bind(PartialMatch, _1, entry.path()))) {
139*795d594fSAndroid Build Coastguard Worker // Avoid unnecessary I/O and SELinux denials.
140*795d594fSAndroid Build Coastguard Worker it.disable_recursion_pending();
141*795d594fSAndroid Build Coastguard Worker continue;
142*795d594fSAndroid Build Coastguard Worker }
143*795d594fSAndroid Build Coastguard Worker std::error_code ec2;
144*795d594fSAndroid Build Coastguard Worker if (entry.is_regular_file(ec2) &&
145*795d594fSAndroid Build Coastguard Worker std::any_of(patterns.begin(), patterns.end(), std::bind(FullMatch, _1, entry.path()))) {
146*795d594fSAndroid Build Coastguard Worker results->push_back(entry.path());
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker if (ec2) {
149*795d594fSAndroid Build Coastguard Worker // It's expected that we don't have permission to stat some dirs/files, and we don't care
150*795d594fSAndroid Build Coastguard Worker // about them.
151*795d594fSAndroid Build Coastguard Worker if (ec2.value() != EACCES) {
152*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << ART_FORMAT("Unable to lstat '{}': {}", entry.path().string(), ec2.message());
153*795d594fSAndroid Build Coastguard Worker }
154*795d594fSAndroid Build Coastguard Worker continue;
155*795d594fSAndroid Build Coastguard Worker }
156*795d594fSAndroid Build Coastguard Worker }
157*795d594fSAndroid Build Coastguard Worker if (ec) {
158*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << ART_FORMAT("Unable to walk through '{}': {}", root_dir.string(), ec.message());
159*795d594fSAndroid Build Coastguard Worker }
160*795d594fSAndroid Build Coastguard Worker }
161*795d594fSAndroid Build Coastguard Worker
162*795d594fSAndroid Build Coastguard Worker } // namespace
163*795d594fSAndroid Build Coastguard Worker
Glob(const std::vector<std::string> & patterns,std::string_view root_dir)164*795d594fSAndroid Build Coastguard Worker std::vector<std::string> Glob(const std::vector<std::string>& patterns, std::string_view root_dir) {
165*795d594fSAndroid Build Coastguard Worker std::vector<std::filesystem::path> parsed_patterns;
166*795d594fSAndroid Build Coastguard Worker parsed_patterns.reserve(patterns.size());
167*795d594fSAndroid Build Coastguard Worker for (std::string_view pattern : patterns) {
168*795d594fSAndroid Build Coastguard Worker parsed_patterns.emplace_back(pattern);
169*795d594fSAndroid Build Coastguard Worker }
170*795d594fSAndroid Build Coastguard Worker std::vector<std::string> results;
171*795d594fSAndroid Build Coastguard Worker MatchGlobRecursive(parsed_patterns, root_dir, &results);
172*795d594fSAndroid Build Coastguard Worker return results;
173*795d594fSAndroid Build Coastguard Worker }
174*795d594fSAndroid Build Coastguard Worker
EscapeGlob(const std::string & str)175*795d594fSAndroid Build Coastguard Worker std::string EscapeGlob(const std::string& str) {
176*795d594fSAndroid Build Coastguard Worker return std::regex_replace(str, std::regex(R"re(\*|\?|\[)re"), "[$&]");
177*795d594fSAndroid Build Coastguard Worker }
178*795d594fSAndroid Build Coastguard Worker
PathStartsWith(std::string_view path,std::string_view prefix)179*795d594fSAndroid Build Coastguard Worker bool PathStartsWith(std::string_view path, std::string_view prefix) {
180*795d594fSAndroid Build Coastguard Worker CHECK(!prefix.empty() && !path.empty() && prefix[0] == '/' && path[0] == '/')
181*795d594fSAndroid Build Coastguard Worker << ART_FORMAT("path={}, prefix={}", path, prefix);
182*795d594fSAndroid Build Coastguard Worker ConsumeSuffix(&prefix, "/");
183*795d594fSAndroid Build Coastguard Worker return path.starts_with(prefix) &&
184*795d594fSAndroid Build Coastguard Worker (path.length() == prefix.length() || path[prefix.length()] == '/');
185*795d594fSAndroid Build Coastguard Worker }
186*795d594fSAndroid Build Coastguard Worker
GetProcMountsMatches(function_ref<bool (std::string_view)> predicate)187*795d594fSAndroid Build Coastguard Worker static Result<std::vector<FstabEntry>> GetProcMountsMatches(
188*795d594fSAndroid Build Coastguard Worker function_ref<bool(std::string_view)> predicate) {
189*795d594fSAndroid Build Coastguard Worker Fstab fstab;
190*795d594fSAndroid Build Coastguard Worker if (!ReadFstabFromProcMounts(&fstab)) {
191*795d594fSAndroid Build Coastguard Worker return Errorf("Failed to read fstab from /proc/mounts");
192*795d594fSAndroid Build Coastguard Worker }
193*795d594fSAndroid Build Coastguard Worker std::vector<FstabEntry> entries;
194*795d594fSAndroid Build Coastguard Worker for (FstabEntry& entry : fstab) {
195*795d594fSAndroid Build Coastguard Worker // Ignore swap areas as a swap area doesn't have a meaningful `mount_point` (a.k.a., `fs_file`)
196*795d594fSAndroid Build Coastguard Worker // field, according to fstab(5). In addition, ignore any other entries whose mount points are
197*795d594fSAndroid Build Coastguard Worker // not absolute paths, just in case there are other fs types that also have an meaningless mount
198*795d594fSAndroid Build Coastguard Worker // point.
199*795d594fSAndroid Build Coastguard Worker if (entry.fs_type == "swap" || !entry.mount_point.starts_with('/')) {
200*795d594fSAndroid Build Coastguard Worker continue;
201*795d594fSAndroid Build Coastguard Worker }
202*795d594fSAndroid Build Coastguard Worker if (predicate(entry.mount_point)) {
203*795d594fSAndroid Build Coastguard Worker entries.push_back(std::move(entry));
204*795d594fSAndroid Build Coastguard Worker }
205*795d594fSAndroid Build Coastguard Worker }
206*795d594fSAndroid Build Coastguard Worker return entries;
207*795d594fSAndroid Build Coastguard Worker }
208*795d594fSAndroid Build Coastguard Worker
GetProcMountsAncestorsOfPath(std::string_view path)209*795d594fSAndroid Build Coastguard Worker Result<std::vector<FstabEntry>> GetProcMountsAncestorsOfPath(std::string_view path) {
210*795d594fSAndroid Build Coastguard Worker return GetProcMountsMatches(
211*795d594fSAndroid Build Coastguard Worker [&](std::string_view mount_point) { return PathStartsWith(path, mount_point); });
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker
GetProcMountsDescendantsOfPath(std::string_view path)214*795d594fSAndroid Build Coastguard Worker Result<std::vector<FstabEntry>> GetProcMountsDescendantsOfPath(std::string_view path) {
215*795d594fSAndroid Build Coastguard Worker return GetProcMountsMatches(
216*795d594fSAndroid Build Coastguard Worker [&](std::string_view mount_point) { return PathStartsWith(mount_point, path); });
217*795d594fSAndroid Build Coastguard Worker }
218*795d594fSAndroid Build Coastguard Worker
EnsureNoProcessInDir(const std::string & dir,uint32_t timeout_ms,bool try_kill)219*795d594fSAndroid Build Coastguard Worker Result<void> EnsureNoProcessInDir(const std::string& dir, uint32_t timeout_ms, bool try_kill) {
220*795d594fSAndroid Build Coastguard Worker // Pairs of pid and process name, indexed by pidfd.
221*795d594fSAndroid Build Coastguard Worker std::unordered_map<int, std::pair<pid_t, std::string>> running_processes;
222*795d594fSAndroid Build Coastguard Worker std::vector<struct pollfd> pollfds;
223*795d594fSAndroid Build Coastguard Worker std::vector<unique_fd> pidfds;
224*795d594fSAndroid Build Coastguard Worker
225*795d594fSAndroid Build Coastguard Worker for (pid_t pid : AllPids()) {
226*795d594fSAndroid Build Coastguard Worker std::string exe;
227*795d594fSAndroid Build Coastguard Worker if (!Readlink(ART_FORMAT("/proc/{}/exe", pid), &exe)) {
228*795d594fSAndroid Build Coastguard Worker // The caller may not have access to all processes. That's okay. When using this method, we
229*795d594fSAndroid Build Coastguard Worker // must grant the caller access to the processes that we are interested in.
230*795d594fSAndroid Build Coastguard Worker continue;
231*795d594fSAndroid Build Coastguard Worker }
232*795d594fSAndroid Build Coastguard Worker
233*795d594fSAndroid Build Coastguard Worker if (PathStartsWith(exe, dir)) {
234*795d594fSAndroid Build Coastguard Worker unique_fd pidfd = PidfdOpen(pid, /*flags=*/0);
235*795d594fSAndroid Build Coastguard Worker if (pidfd < 0) {
236*795d594fSAndroid Build Coastguard Worker if (errno == ESRCH) {
237*795d594fSAndroid Build Coastguard Worker // The process has gone now.
238*795d594fSAndroid Build Coastguard Worker continue;
239*795d594fSAndroid Build Coastguard Worker }
240*795d594fSAndroid Build Coastguard Worker return ErrnoErrorf("Failed to pidfd_open {}", pid);
241*795d594fSAndroid Build Coastguard Worker }
242*795d594fSAndroid Build Coastguard Worker
243*795d594fSAndroid Build Coastguard Worker std::string name;
244*795d594fSAndroid Build Coastguard Worker if (!ReadFileToString(ART_FORMAT("/proc/{}/comm", pid), &name)) {
245*795d594fSAndroid Build Coastguard Worker PLOG(WARNING) << "Failed to get process name for pid " << pid;
246*795d594fSAndroid Build Coastguard Worker }
247*795d594fSAndroid Build Coastguard Worker size_t pos = name.find_first_of("\n\0");
248*795d594fSAndroid Build Coastguard Worker if (pos != std::string::npos) {
249*795d594fSAndroid Build Coastguard Worker name.resize(pos);
250*795d594fSAndroid Build Coastguard Worker }
251*795d594fSAndroid Build Coastguard Worker LOG(INFO) << ART_FORMAT(
252*795d594fSAndroid Build Coastguard Worker "Process '{}' (pid: {}) is still running. Waiting for it to exit", name, pid);
253*795d594fSAndroid Build Coastguard Worker
254*795d594fSAndroid Build Coastguard Worker struct pollfd& pollfd = pollfds.emplace_back();
255*795d594fSAndroid Build Coastguard Worker pollfd.fd = pidfd.get();
256*795d594fSAndroid Build Coastguard Worker pollfd.events = POLLIN;
257*795d594fSAndroid Build Coastguard Worker
258*795d594fSAndroid Build Coastguard Worker running_processes[pidfd.get()] = std::make_pair(pid, std::move(name));
259*795d594fSAndroid Build Coastguard Worker pidfds.push_back(std::move(pidfd));
260*795d594fSAndroid Build Coastguard Worker }
261*795d594fSAndroid Build Coastguard Worker }
262*795d594fSAndroid Build Coastguard Worker
263*795d594fSAndroid Build Coastguard Worker auto wait_for_processes = [&]() -> Result<void> {
264*795d594fSAndroid Build Coastguard Worker uint64_t start_time_ms = MilliTime();
265*795d594fSAndroid Build Coastguard Worker uint64_t remaining_timeout_ms = timeout_ms;
266*795d594fSAndroid Build Coastguard Worker while (!running_processes.empty() && remaining_timeout_ms > 0) {
267*795d594fSAndroid Build Coastguard Worker int poll_ret = TEMP_FAILURE_RETRY(poll(pollfds.data(), pollfds.size(), remaining_timeout_ms));
268*795d594fSAndroid Build Coastguard Worker if (poll_ret < 0) {
269*795d594fSAndroid Build Coastguard Worker return ErrnoErrorf("Failed to poll pidfd's");
270*795d594fSAndroid Build Coastguard Worker }
271*795d594fSAndroid Build Coastguard Worker if (poll_ret == 0) {
272*795d594fSAndroid Build Coastguard Worker // Timeout.
273*795d594fSAndroid Build Coastguard Worker break;
274*795d594fSAndroid Build Coastguard Worker }
275*795d594fSAndroid Build Coastguard Worker uint64_t elapsed_time_ms = MilliTime() - start_time_ms;
276*795d594fSAndroid Build Coastguard Worker for (struct pollfd& pollfd : pollfds) {
277*795d594fSAndroid Build Coastguard Worker if (pollfd.fd < 0) {
278*795d594fSAndroid Build Coastguard Worker continue;
279*795d594fSAndroid Build Coastguard Worker }
280*795d594fSAndroid Build Coastguard Worker if ((pollfd.revents & POLLIN) != 0) {
281*795d594fSAndroid Build Coastguard Worker const auto& [pid, name] = running_processes[pollfd.fd];
282*795d594fSAndroid Build Coastguard Worker LOG(INFO) << ART_FORMAT(
283*795d594fSAndroid Build Coastguard Worker "Process '{}' (pid: {}) exited in {}ms", name, pid, elapsed_time_ms);
284*795d594fSAndroid Build Coastguard Worker running_processes.erase(pollfd.fd);
285*795d594fSAndroid Build Coastguard Worker pollfd.fd = -1;
286*795d594fSAndroid Build Coastguard Worker }
287*795d594fSAndroid Build Coastguard Worker }
288*795d594fSAndroid Build Coastguard Worker remaining_timeout_ms = timeout_ms - elapsed_time_ms;
289*795d594fSAndroid Build Coastguard Worker }
290*795d594fSAndroid Build Coastguard Worker return {};
291*795d594fSAndroid Build Coastguard Worker };
292*795d594fSAndroid Build Coastguard Worker
293*795d594fSAndroid Build Coastguard Worker OR_RETURN(wait_for_processes());
294*795d594fSAndroid Build Coastguard Worker
295*795d594fSAndroid Build Coastguard Worker bool process_killed = false;
296*795d594fSAndroid Build Coastguard Worker for (const auto& [pidfd, pair] : running_processes) {
297*795d594fSAndroid Build Coastguard Worker const auto& [pid, name] = pair;
298*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << ART_FORMAT(
299*795d594fSAndroid Build Coastguard Worker "Process '{}' (pid: {}) is still running after {}ms", name, pid, timeout_ms);
300*795d594fSAndroid Build Coastguard Worker if (try_kill) {
301*795d594fSAndroid Build Coastguard Worker LOG(INFO) << ART_FORMAT("Killing '{}' (pid: {})", name, pid);
302*795d594fSAndroid Build Coastguard Worker if (kill(pid, SIGKILL) != 0) {
303*795d594fSAndroid Build Coastguard Worker PLOG(ERROR) << ART_FORMAT("Failed to kill '{}' (pid: {})", name, pid);
304*795d594fSAndroid Build Coastguard Worker }
305*795d594fSAndroid Build Coastguard Worker process_killed = true;
306*795d594fSAndroid Build Coastguard Worker }
307*795d594fSAndroid Build Coastguard Worker }
308*795d594fSAndroid Build Coastguard Worker
309*795d594fSAndroid Build Coastguard Worker if (process_killed) {
310*795d594fSAndroid Build Coastguard Worker // Wait another round for processes to exit after being killed.
311*795d594fSAndroid Build Coastguard Worker OR_RETURN(wait_for_processes());
312*795d594fSAndroid Build Coastguard Worker }
313*795d594fSAndroid Build Coastguard Worker if (!running_processes.empty()) {
314*795d594fSAndroid Build Coastguard Worker return Errorf("Some process(es) are still running after {}ms", timeout_ms);
315*795d594fSAndroid Build Coastguard Worker }
316*795d594fSAndroid Build Coastguard Worker return {};
317*795d594fSAndroid Build Coastguard Worker }
318*795d594fSAndroid Build Coastguard Worker
319*795d594fSAndroid Build Coastguard Worker } // namespace tools
320*795d594fSAndroid Build Coastguard Worker } // namespace art
321