1 /* 2 * Copyright (C) 2019 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 #define TRACE_TAG FDEVENT 18 19 #include "sysdeps.h" 20 #include "fdevent_poll.h" 21 22 #include <fcntl.h> 23 #include <inttypes.h> 24 #include <stdint.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <unistd.h> 28 29 #include <atomic> 30 #include <deque> 31 #include <functional> 32 #include <list> 33 #include <mutex> 34 #include <optional> 35 #include <unordered_map> 36 #include <utility> 37 #include <variant> 38 #include <vector> 39 40 #include <android-base/chrono_utils.h> 41 #include <android-base/file.h> 42 #include <android-base/logging.h> 43 #include <android-base/stringprintf.h> 44 #include <android-base/threads.h> 45 46 #include "adb_io.h" 47 #include "adb_trace.h" 48 #include "adb_unique_fd.h" 49 #include "adb_utils.h" 50 #include "fdevent.h" 51 #include "sysdeps/chrono.h" 52 53 static void fdevent_interrupt(int fd, unsigned, void*) { 54 char buf[BUFSIZ]; 55 ssize_t rc = TEMP_FAILURE_RETRY(adb_read(fd, buf, sizeof(buf))); 56 if (rc == -1) { 57 PLOG(FATAL) << "failed to read from fdevent interrupt fd"; 58 } 59 } 60 61 fdevent_context_poll::fdevent_context_poll() { 62 int s[2]; 63 if (adb_socketpair(s) != 0) { 64 PLOG(FATAL) << "failed to create fdevent interrupt socketpair"; 65 } 66 67 if (!set_file_block_mode(s[0], false) || !set_file_block_mode(s[1], false)) { 68 PLOG(FATAL) << "failed to make fdevent interrupt socket nonblocking"; 69 } 70 71 this->interrupt_fd_.reset(s[0]); 72 fdevent* fde = this->Create(unique_fd(s[1]), fdevent_interrupt, nullptr); 73 CHECK(fde != nullptr); 74 this->Add(fde, FDE_READ); 75 } 76 77 fdevent_context_poll::~fdevent_context_poll() { 78 // Destroy calls virtual methods, but this class is final, so that's okay. 79 this->Destroy(this->interrupt_fde_); 80 } 81 82 void fdevent_context_poll::Set(fdevent* fde, unsigned events) { 83 CheckMainThread(); 84 fde->state = events; 85 D("fdevent_set: %s, events = %u", dump_fde(fde).c_str(), events); 86 } 87 88 static std::string dump_pollfds(const std::vector<adb_pollfd>& pollfds) { 89 std::string result; 90 for (const auto& pollfd : pollfds) { 91 std::string op; 92 if (pollfd.events & POLLIN) { 93 op += "R"; 94 } 95 if (pollfd.events & POLLOUT) { 96 op += "W"; 97 } 98 android::base::StringAppendF(&result, " %d(%s)", pollfd.fd, op.c_str()); 99 } 100 return result; 101 } 102 103 void fdevent_context_poll::Loop() { 104 main_thread_id_ = android::base::GetThreadId(); 105 106 std::vector<adb_pollfd> pollfds; 107 std::vector<fdevent_event> poll_events; 108 109 while (true) { 110 if (terminate_loop_) { 111 break; 112 } 113 114 D("--- --- waiting for events"); 115 pollfds.clear(); 116 for (const auto& [fd, fde] : this->installed_fdevents_) { 117 adb_pollfd pfd; 118 pfd.fd = fd; 119 pfd.events = 0; 120 if (fde.state & FDE_READ) { 121 pfd.events |= POLLIN; 122 } 123 if (fde.state & FDE_WRITE) { 124 pfd.events |= POLLOUT; 125 } 126 if (fde.state & FDE_ERROR) { 127 pfd.events |= POLLERR; 128 } 129 #if defined(__linux__) 130 pfd.events |= POLLRDHUP; 131 #endif 132 pfd.revents = 0; 133 pollfds.push_back(pfd); 134 } 135 CHECK_GT(pollfds.size(), 0u); 136 D("poll(), pollfds = %s", dump_pollfds(pollfds).c_str()); 137 138 std::optional<std::chrono::milliseconds> timeout = CalculatePollDuration(); 139 int timeout_ms; 140 if (!timeout) { 141 timeout_ms = -1; 142 } else { 143 timeout_ms = timeout->count(); 144 } 145 146 int ret = adb_poll(pollfds.data(), pollfds.size(), timeout_ms); 147 if (ret == -1) { 148 PLOG(ERROR) << "poll(), ret = " << ret; 149 return; 150 } 151 152 auto post_poll = std::chrono::steady_clock::now(); 153 154 for (const auto& pollfd : pollfds) { 155 unsigned events = 0; 156 if (pollfd.revents & POLLIN) { 157 events |= FDE_READ; 158 } 159 if (pollfd.revents & POLLOUT) { 160 events |= FDE_WRITE; 161 } 162 if (pollfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { 163 // We fake a read, as the rest of the code assumes that errors will 164 // be detected at that point. 165 events |= FDE_READ | FDE_ERROR; 166 } 167 #if defined(__linux__) 168 if (pollfd.revents & POLLRDHUP) { 169 events |= FDE_READ | FDE_ERROR; 170 } 171 #endif 172 173 auto it = this->installed_fdevents_.find(pollfd.fd); 174 CHECK(it != this->installed_fdevents_.end()); 175 fdevent* fde = &it->second; 176 177 if (events == 0) { 178 if (fde->timeout) { 179 auto deadline = fde->last_active + *fde->timeout; 180 if (deadline < post_poll) { 181 events |= FDE_TIMEOUT; 182 } 183 } 184 } 185 186 if (events != 0) { 187 D("%s got events %x", dump_fde(fde).c_str(), events); 188 poll_events.push_back({fde, events}); 189 fde->last_active = post_poll; 190 } 191 } 192 this->HandleEvents(poll_events); 193 poll_events.clear(); 194 } 195 196 main_thread_id_.reset(); 197 } 198 199 size_t fdevent_context_poll::InstalledCount() { 200 // We always have an installed fde for interrupt. 201 return this->installed_fdevents_.size() - 1; 202 } 203 204 void fdevent_context_poll::Interrupt() { 205 int rc = adb_write(this->interrupt_fd_, "", 1); 206 207 // It's possible that we get EAGAIN here, if lots of notifications came in while handling. 208 if (rc == 0) { 209 PLOG(FATAL) << "fdevent interrupt fd was closed?"; 210 } else if (rc == -1 && errno != EAGAIN) { 211 PLOG(FATAL) << "failed to write to fdevent interrupt fd"; 212 } 213 } 214 215 void fdevent_context_poll::Register(fdevent*) {} 216 217 void fdevent_context_poll::Unregister(fdevent*) {} 218