blob: 04819ec75a09db146917b078ba8c9d5f3597d586 [file] [log] [blame]
Joe Onorato1754d742016-11-21 17:51:35 -08001/*
2 * Copyright (C) 2016 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 */
Yi Jin4e843102018-02-14 15:36:18 -080016#define DEBUG false
Yi Jinb592e3b2018-02-01 15:17:04 -080017#include "Log.h"
Joe Onorato1754d742016-11-21 17:51:35 -080018
19#include "FdBuffer.h"
20
Mike Ma35056662018-12-06 13:32:59 -080021#include <log/log.h>
Joe Onorato1754d742016-11-21 17:51:35 -080022#include <utils/SystemClock.h>
23
24#include <fcntl.h>
25#include <poll.h>
26#include <unistd.h>
Yi Jin0a3406f2017-06-22 19:23:11 -070027#include <wait.h>
Joe Onorato1754d742016-11-21 17:51:35 -080028
Yi Jin6cacbcb2018-03-30 14:04:52 -070029namespace android {
30namespace os {
31namespace incidentd {
32
Yi Jinb592e3b2018-02-01 15:17:04 -080033const ssize_t BUFFER_SIZE = 16 * 1024; // 16 KB
34const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
Joe Onorato1754d742016-11-21 17:51:35 -080035
Joe Onorato1754d742016-11-21 17:51:35 -080036FdBuffer::FdBuffer()
Yi Jinb592e3b2018-02-01 15:17:04 -080037 : mBuffer(BUFFER_SIZE), mStartTime(-1), mFinishTime(-1), mTimedOut(false), mTruncated(false) {}
Joe Onorato1754d742016-11-21 17:51:35 -080038
Yi Jinb592e3b2018-02-01 15:17:04 -080039FdBuffer::~FdBuffer() {}
Joe Onorato1754d742016-11-21 17:51:35 -080040
Yi Jine3dab2d2018-03-22 16:56:39 -070041status_t FdBuffer::read(int fd, int64_t timeout) {
42 struct pollfd pfds = {.fd = fd, .events = POLLIN};
Joe Onorato1754d742016-11-21 17:51:35 -080043 mStartTime = uptimeMillis();
44
Yi Jine3dab2d2018-03-22 16:56:39 -070045 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
Joe Onorato1754d742016-11-21 17:51:35 -080046
Joe Onorato1754d742016-11-21 17:51:35 -080047 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -070048 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
49 mTruncated = true;
Mike Ma28381692018-12-04 15:46:29 -080050 VLOG("Truncating data");
Yi Jinc23fad22017-09-15 17:24:59 -070051 break;
Joe Onorato1754d742016-11-21 17:51:35 -080052 }
Mike Ma28381692018-12-04 15:46:29 -080053 if (mBuffer.writeBuffer() == NULL) {
54 VLOG("No memory");
55 return NO_MEMORY;
56 }
Joe Onorato1754d742016-11-21 17:51:35 -080057
58 int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
59 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080060 VLOG("timed out due to long read");
Joe Onorato1754d742016-11-21 17:51:35 -080061 mTimedOut = true;
62 break;
63 }
64
Mike Ma28381692018-12-04 15:46:29 -080065 int count = TEMP_FAILURE_RETRY(poll(&pfds, 1, remainingTime));
Joe Onorato1754d742016-11-21 17:51:35 -080066 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080067 VLOG("timed out due to block calling poll");
Joe Onorato1754d742016-11-21 17:51:35 -080068 mTimedOut = true;
69 break;
70 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080071 VLOG("poll failed: %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080072 return -errno;
73 } else {
74 if ((pfds.revents & POLLERR) != 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080075 VLOG("return event has error %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080076 return errno != 0 ? -errno : UNKNOWN_ERROR;
77 } else {
Yi Jin0e5d5772018-04-20 11:16:10 -070078 ssize_t amt = TEMP_FAILURE_RETRY(
79 ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite()));
Joe Onorato1754d742016-11-21 17:51:35 -080080 if (amt < 0) {
81 if (errno == EAGAIN || errno == EWOULDBLOCK) {
82 continue;
83 } else {
Yi Jine3dab2d2018-03-22 16:56:39 -070084 VLOG("Fail to read %d: %s", fd, strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080085 return -errno;
86 }
87 } else if (amt == 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -070088 VLOG("Reached EOF of fd=%d", fd);
Joe Onorato1754d742016-11-21 17:51:35 -080089 break;
90 }
Yi Jinc23fad22017-09-15 17:24:59 -070091 mBuffer.wp()->move(amt);
Joe Onorato1754d742016-11-21 17:51:35 -080092 }
93 }
94 }
Joe Onorato1754d742016-11-21 17:51:35 -080095 mFinishTime = uptimeMillis();
96 return NO_ERROR;
97}
98
Yi Jine3dab2d2018-03-22 16:56:39 -070099status_t FdBuffer::readFully(int fd) {
Kweku Adamseadd1232018-02-05 16:45:13 -0800100 mStartTime = uptimeMillis();
101
102 while (true) {
103 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
104 // Don't let it get too big.
105 mTruncated = true;
106 VLOG("Truncating data");
107 break;
108 }
Mike Ma28381692018-12-04 15:46:29 -0800109 if (mBuffer.writeBuffer() == NULL) {
110 VLOG("No memory");
111 return NO_MEMORY;
112 }
Kweku Adamseadd1232018-02-05 16:45:13 -0800113
Yi Jine3dab2d2018-03-22 16:56:39 -0700114 ssize_t amt =
115 TEMP_FAILURE_RETRY(::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite()));
Kweku Adamseadd1232018-02-05 16:45:13 -0800116 if (amt < 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700117 VLOG("Fail to read %d: %s", fd, strerror(errno));
Kweku Adamseadd1232018-02-05 16:45:13 -0800118 return -errno;
119 } else if (amt == 0) {
120 VLOG("Done reading %zu bytes", mBuffer.size());
121 // We're done.
122 break;
123 }
124 mBuffer.wp()->move(amt);
125 }
126
127 mFinishTime = uptimeMillis();
128 return NO_ERROR;
129}
130
Yi Jine3dab2d2018-03-22 16:56:39 -0700131status_t FdBuffer::readProcessedDataInStream(int fd, unique_fd toFd, unique_fd fromFd,
Yi Jin6355d2f2018-03-14 15:18:02 -0700132 int64_t timeoutMs, const bool isSysfs) {
Yi Jin0a3406f2017-06-22 19:23:11 -0700133 struct pollfd pfds[] = {
Yi Jine3dab2d2018-03-22 16:56:39 -0700134 {.fd = fd, .events = POLLIN},
135 {.fd = toFd.get(), .events = POLLOUT},
136 {.fd = fromFd.get(), .events = POLLIN},
Yi Jin0a3406f2017-06-22 19:23:11 -0700137 };
138
139 mStartTime = uptimeMillis();
140
141 // mark all fds non blocking
Yi Jine3dab2d2018-03-22 16:56:39 -0700142 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
143 fcntl(toFd.get(), F_SETFL, fcntl(toFd.get(), F_GETFL, 0) | O_NONBLOCK);
144 fcntl(fromFd.get(), F_SETFL, fcntl(fromFd.get(), F_GETFL, 0) | O_NONBLOCK);
Yi Jin0a3406f2017-06-22 19:23:11 -0700145
146 // A circular buffer holds data read from fd and writes to parsing process
147 uint8_t cirBuf[BUFFER_SIZE];
148 size_t cirSize = 0;
149 int rpos = 0, wpos = 0;
150
151 // This is the buffer used to store processed data
Yi Jin0a3406f2017-06-22 19:23:11 -0700152 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -0700153 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
Mike Ma28381692018-12-04 15:46:29 -0800154 VLOG("Truncating data");
Yi Jinc23fad22017-09-15 17:24:59 -0700155 mTruncated = true;
156 break;
Yi Jin0a3406f2017-06-22 19:23:11 -0700157 }
Mike Ma28381692018-12-04 15:46:29 -0800158 if (mBuffer.writeBuffer() == NULL) {
159 VLOG("No memory");
160 return NO_MEMORY;
161 }
Yi Jin0a3406f2017-06-22 19:23:11 -0700162
163 int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
164 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800165 VLOG("timed out due to long read");
Yi Jin0a3406f2017-06-22 19:23:11 -0700166 mTimedOut = true;
167 break;
168 }
169
170 // wait for any pfds to be ready to perform IO
Mike Ma28381692018-12-04 15:46:29 -0800171 int count = TEMP_FAILURE_RETRY(poll(pfds, 3, remainingTime));
Yi Jin0a3406f2017-06-22 19:23:11 -0700172 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800173 VLOG("timed out due to block calling poll");
Yi Jin0a3406f2017-06-22 19:23:11 -0700174 mTimedOut = true;
175 break;
176 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800177 VLOG("Fail to poll: %s", strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700178 return -errno;
179 }
180
181 // make sure no errors occur on any fds
182 for (int i = 0; i < 3; ++i) {
183 if ((pfds[i].revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800184 if (i == 0 && isSysfs) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700185 VLOG("fd %d is sysfs, ignore its POLLERR return value", fd);
Yi Jin0eb22342017-11-06 17:17:27 -0800186 continue;
187 }
Yi Jine3dab2d2018-03-22 16:56:39 -0700188 VLOG("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700189 return errno != 0 ? -errno : UNKNOWN_ERROR;
190 }
191 }
192
193 // read from fd
194 if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
195 ssize_t amt;
196 if (rpos >= wpos) {
Yi Jin0e5d5772018-04-20 11:16:10 -0700197 amt = TEMP_FAILURE_RETRY(::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700198 } else {
Yi Jin0e5d5772018-04-20 11:16:10 -0700199 amt = TEMP_FAILURE_RETRY(::read(fd, cirBuf + rpos, wpos - rpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700200 }
201 if (amt < 0) {
202 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700203 VLOG("Fail to read fd %d: %s", fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700204 return -errno;
Yi Jin1a11fa12018-02-22 16:44:10 -0800205 } // otherwise just continue
206 } else if (amt == 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700207 VLOG("Reached EOF of input file %d", fd);
Yi Jin1a11fa12018-02-22 16:44:10 -0800208 pfds[0].fd = -1; // reach EOF so don't have to poll pfds[0].
Yi Jin0a3406f2017-06-22 19:23:11 -0700209 } else {
210 rpos += amt;
211 cirSize += amt;
212 }
213 }
214
215 // write to parsing process
216 if (cirSize > 0 && pfds[1].fd != -1) {
217 ssize_t amt;
218 if (rpos > wpos) {
Yi Jin0e5d5772018-04-20 11:16:10 -0700219 amt = TEMP_FAILURE_RETRY(::write(toFd.get(), cirBuf + wpos, rpos - wpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700220 } else {
Yi Jin0e5d5772018-04-20 11:16:10 -0700221 amt = TEMP_FAILURE_RETRY(::write(toFd.get(), cirBuf + wpos, BUFFER_SIZE - wpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700222 }
223 if (amt < 0) {
224 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jin6cacbcb2018-03-30 14:04:52 -0700225 VLOG("Fail to write toFd %d: %s", toFd.get(), strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700226 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800227 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700228 } else {
229 wpos += amt;
230 cirSize -= amt;
231 }
232 }
233
234 // if buffer is empty and fd is closed, close write fd.
235 if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700236 VLOG("Close write pipe %d", toFd.get());
237 toFd.reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700238 pfds[1].fd = -1;
239 }
240
241 // circular buffer, reset rpos and wpos
242 if (rpos >= BUFFER_SIZE) {
243 rpos = 0;
244 }
245 if (wpos >= BUFFER_SIZE) {
246 wpos = 0;
247 }
248
249 // read from parsing process
Yi Jin0e5d5772018-04-20 11:16:10 -0700250 ssize_t amt = TEMP_FAILURE_RETRY(
251 ::read(fromFd.get(), mBuffer.writeBuffer(), mBuffer.currentToWrite()));
Yi Jin0a3406f2017-06-22 19:23:11 -0700252 if (amt < 0) {
253 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinea31cbe2018-04-02 11:09:57 -0700254 VLOG("Fail to read fromFd %d: %s", fromFd.get(), strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700255 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800256 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700257 } else if (amt == 0) {
Yi Jinea31cbe2018-04-02 11:09:57 -0700258 VLOG("Reached EOF of fromFd %d", fromFd.get());
Yi Jin0a3406f2017-06-22 19:23:11 -0700259 break;
260 } else {
Yi Jinc23fad22017-09-15 17:24:59 -0700261 mBuffer.wp()->move(amt);
Yi Jin0a3406f2017-06-22 19:23:11 -0700262 }
263 }
264
265 mFinishTime = uptimeMillis();
266 return NO_ERROR;
267}
268
Yi Jinb592e3b2018-02-01 15:17:04 -0800269size_t FdBuffer::size() const { return mBuffer.size(); }
Joe Onorato1754d742016-11-21 17:51:35 -0800270
Yi Jinb592e3b2018-02-01 15:17:04 -0800271EncodedBuffer::iterator FdBuffer::data() const { return mBuffer.begin(); }
Yi Jin6cacbcb2018-03-30 14:04:52 -0700272
273} // namespace incidentd
274} // namespace os
275} // namespace android