blob: 685c0677c8fa427b2b553dd5afc762bf61c51b73 [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()
Joe Onorato99598ee2019-02-11 15:55:13 +000037 :mBuffer(new EncodedBuffer(BUFFER_SIZE)),
38 mStartTime(-1),
39 mFinishTime(-1),
40 mTimedOut(false),
41 mTruncated(false) {
42}
Joe Onorato1754d742016-11-21 17:51:35 -080043
Joe Onorato99598ee2019-02-11 15:55:13 +000044FdBuffer::~FdBuffer() {
45}
Joe Onorato1754d742016-11-21 17:51:35 -080046
Yi Jine3dab2d2018-03-22 16:56:39 -070047status_t FdBuffer::read(int fd, int64_t timeout) {
48 struct pollfd pfds = {.fd = fd, .events = POLLIN};
Joe Onorato1754d742016-11-21 17:51:35 -080049 mStartTime = uptimeMillis();
50
Yi Jine3dab2d2018-03-22 16:56:39 -070051 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
Joe Onorato1754d742016-11-21 17:51:35 -080052
Joe Onorato1754d742016-11-21 17:51:35 -080053 while (true) {
Joe Onorato99598ee2019-02-11 15:55:13 +000054 if (mBuffer->size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
Yi Jinc23fad22017-09-15 17:24:59 -070055 mTruncated = true;
Mike Ma28381692018-12-04 15:46:29 -080056 VLOG("Truncating data");
Yi Jinc23fad22017-09-15 17:24:59 -070057 break;
Joe Onorato1754d742016-11-21 17:51:35 -080058 }
Joe Onorato99598ee2019-02-11 15:55:13 +000059 if (mBuffer->writeBuffer() == NULL) {
Mike Ma28381692018-12-04 15:46:29 -080060 VLOG("No memory");
61 return NO_MEMORY;
62 }
Joe Onorato1754d742016-11-21 17:51:35 -080063
64 int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
65 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080066 VLOG("timed out due to long read");
Joe Onorato1754d742016-11-21 17:51:35 -080067 mTimedOut = true;
68 break;
69 }
70
Mike Ma28381692018-12-04 15:46:29 -080071 int count = TEMP_FAILURE_RETRY(poll(&pfds, 1, remainingTime));
Joe Onorato1754d742016-11-21 17:51:35 -080072 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080073 VLOG("timed out due to block calling poll");
Joe Onorato1754d742016-11-21 17:51:35 -080074 mTimedOut = true;
75 break;
76 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080077 VLOG("poll failed: %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080078 return -errno;
79 } else {
80 if ((pfds.revents & POLLERR) != 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080081 VLOG("return event has error %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080082 return errno != 0 ? -errno : UNKNOWN_ERROR;
83 } else {
Yi Jin0e5d5772018-04-20 11:16:10 -070084 ssize_t amt = TEMP_FAILURE_RETRY(
Joe Onorato99598ee2019-02-11 15:55:13 +000085 ::read(fd, mBuffer->writeBuffer(), mBuffer->currentToWrite()));
Joe Onorato1754d742016-11-21 17:51:35 -080086 if (amt < 0) {
87 if (errno == EAGAIN || errno == EWOULDBLOCK) {
88 continue;
89 } else {
Yi Jine3dab2d2018-03-22 16:56:39 -070090 VLOG("Fail to read %d: %s", fd, strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080091 return -errno;
92 }
93 } else if (amt == 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -070094 VLOG("Reached EOF of fd=%d", fd);
Joe Onorato1754d742016-11-21 17:51:35 -080095 break;
96 }
Joe Onorato99598ee2019-02-11 15:55:13 +000097 mBuffer->wp()->move(amt);
Joe Onorato1754d742016-11-21 17:51:35 -080098 }
99 }
100 }
Joe Onorato1754d742016-11-21 17:51:35 -0800101 mFinishTime = uptimeMillis();
102 return NO_ERROR;
103}
104
Yi Jine3dab2d2018-03-22 16:56:39 -0700105status_t FdBuffer::readFully(int fd) {
Kweku Adamseadd1232018-02-05 16:45:13 -0800106 mStartTime = uptimeMillis();
107
108 while (true) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000109 if (mBuffer->size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
Kweku Adamseadd1232018-02-05 16:45:13 -0800110 // Don't let it get too big.
111 mTruncated = true;
112 VLOG("Truncating data");
113 break;
114 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000115 if (mBuffer->writeBuffer() == NULL) {
Mike Ma28381692018-12-04 15:46:29 -0800116 VLOG("No memory");
117 return NO_MEMORY;
118 }
Kweku Adamseadd1232018-02-05 16:45:13 -0800119
Yi Jine3dab2d2018-03-22 16:56:39 -0700120 ssize_t amt =
Joe Onorato99598ee2019-02-11 15:55:13 +0000121 TEMP_FAILURE_RETRY(::read(fd, mBuffer->writeBuffer(), mBuffer->currentToWrite()));
Kweku Adamseadd1232018-02-05 16:45:13 -0800122 if (amt < 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700123 VLOG("Fail to read %d: %s", fd, strerror(errno));
Kweku Adamseadd1232018-02-05 16:45:13 -0800124 return -errno;
125 } else if (amt == 0) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000126 VLOG("Done reading %zu bytes", mBuffer->size());
Kweku Adamseadd1232018-02-05 16:45:13 -0800127 // We're done.
128 break;
129 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000130 mBuffer->wp()->move(amt);
Kweku Adamseadd1232018-02-05 16:45:13 -0800131 }
132
133 mFinishTime = uptimeMillis();
134 return NO_ERROR;
135}
136
Yi Jine3dab2d2018-03-22 16:56:39 -0700137status_t FdBuffer::readProcessedDataInStream(int fd, unique_fd toFd, unique_fd fromFd,
Yi Jin6355d2f2018-03-14 15:18:02 -0700138 int64_t timeoutMs, const bool isSysfs) {
Yi Jin0a3406f2017-06-22 19:23:11 -0700139 struct pollfd pfds[] = {
Yi Jine3dab2d2018-03-22 16:56:39 -0700140 {.fd = fd, .events = POLLIN},
141 {.fd = toFd.get(), .events = POLLOUT},
142 {.fd = fromFd.get(), .events = POLLIN},
Yi Jin0a3406f2017-06-22 19:23:11 -0700143 };
144
145 mStartTime = uptimeMillis();
146
147 // mark all fds non blocking
Yi Jine3dab2d2018-03-22 16:56:39 -0700148 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
149 fcntl(toFd.get(), F_SETFL, fcntl(toFd.get(), F_GETFL, 0) | O_NONBLOCK);
150 fcntl(fromFd.get(), F_SETFL, fcntl(fromFd.get(), F_GETFL, 0) | O_NONBLOCK);
Yi Jin0a3406f2017-06-22 19:23:11 -0700151
152 // A circular buffer holds data read from fd and writes to parsing process
153 uint8_t cirBuf[BUFFER_SIZE];
154 size_t cirSize = 0;
155 int rpos = 0, wpos = 0;
156
157 // This is the buffer used to store processed data
Yi Jin0a3406f2017-06-22 19:23:11 -0700158 while (true) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000159 if (mBuffer->size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
Mike Ma28381692018-12-04 15:46:29 -0800160 VLOG("Truncating data");
Yi Jinc23fad22017-09-15 17:24:59 -0700161 mTruncated = true;
162 break;
Yi Jin0a3406f2017-06-22 19:23:11 -0700163 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000164 if (mBuffer->writeBuffer() == NULL) {
Mike Ma28381692018-12-04 15:46:29 -0800165 VLOG("No memory");
166 return NO_MEMORY;
167 }
Yi Jin0a3406f2017-06-22 19:23:11 -0700168
169 int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
170 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800171 VLOG("timed out due to long read");
Yi Jin0a3406f2017-06-22 19:23:11 -0700172 mTimedOut = true;
173 break;
174 }
175
176 // wait for any pfds to be ready to perform IO
Mike Ma28381692018-12-04 15:46:29 -0800177 int count = TEMP_FAILURE_RETRY(poll(pfds, 3, remainingTime));
Yi Jin0a3406f2017-06-22 19:23:11 -0700178 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800179 VLOG("timed out due to block calling poll");
Yi Jin0a3406f2017-06-22 19:23:11 -0700180 mTimedOut = true;
181 break;
182 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800183 VLOG("Fail to poll: %s", strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700184 return -errno;
185 }
186
187 // make sure no errors occur on any fds
188 for (int i = 0; i < 3; ++i) {
189 if ((pfds[i].revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800190 if (i == 0 && isSysfs) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700191 VLOG("fd %d is sysfs, ignore its POLLERR return value", fd);
Yi Jin0eb22342017-11-06 17:17:27 -0800192 continue;
193 }
Yi Jine3dab2d2018-03-22 16:56:39 -0700194 VLOG("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700195 return errno != 0 ? -errno : UNKNOWN_ERROR;
196 }
197 }
198
199 // read from fd
200 if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
201 ssize_t amt;
202 if (rpos >= wpos) {
Yi Jin0e5d5772018-04-20 11:16:10 -0700203 amt = TEMP_FAILURE_RETRY(::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700204 } else {
Yi Jin0e5d5772018-04-20 11:16:10 -0700205 amt = TEMP_FAILURE_RETRY(::read(fd, cirBuf + rpos, wpos - rpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700206 }
207 if (amt < 0) {
208 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700209 VLOG("Fail to read fd %d: %s", fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700210 return -errno;
Yi Jin1a11fa12018-02-22 16:44:10 -0800211 } // otherwise just continue
212 } else if (amt == 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700213 VLOG("Reached EOF of input file %d", fd);
Yi Jin1a11fa12018-02-22 16:44:10 -0800214 pfds[0].fd = -1; // reach EOF so don't have to poll pfds[0].
Yi Jin0a3406f2017-06-22 19:23:11 -0700215 } else {
216 rpos += amt;
217 cirSize += amt;
218 }
219 }
220
221 // write to parsing process
222 if (cirSize > 0 && pfds[1].fd != -1) {
223 ssize_t amt;
224 if (rpos > wpos) {
Yi Jin0e5d5772018-04-20 11:16:10 -0700225 amt = TEMP_FAILURE_RETRY(::write(toFd.get(), cirBuf + wpos, rpos - wpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700226 } else {
Yi Jin0e5d5772018-04-20 11:16:10 -0700227 amt = TEMP_FAILURE_RETRY(::write(toFd.get(), cirBuf + wpos, BUFFER_SIZE - wpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700228 }
229 if (amt < 0) {
230 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jin6cacbcb2018-03-30 14:04:52 -0700231 VLOG("Fail to write toFd %d: %s", toFd.get(), strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700232 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800233 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700234 } else {
235 wpos += amt;
236 cirSize -= amt;
237 }
238 }
239
240 // if buffer is empty and fd is closed, close write fd.
241 if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700242 VLOG("Close write pipe %d", toFd.get());
243 toFd.reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700244 pfds[1].fd = -1;
245 }
246
247 // circular buffer, reset rpos and wpos
248 if (rpos >= BUFFER_SIZE) {
249 rpos = 0;
250 }
251 if (wpos >= BUFFER_SIZE) {
252 wpos = 0;
253 }
254
255 // read from parsing process
Yi Jin0e5d5772018-04-20 11:16:10 -0700256 ssize_t amt = TEMP_FAILURE_RETRY(
Joe Onorato99598ee2019-02-11 15:55:13 +0000257 ::read(fromFd.get(), mBuffer->writeBuffer(), mBuffer->currentToWrite()));
Yi Jin0a3406f2017-06-22 19:23:11 -0700258 if (amt < 0) {
259 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinea31cbe2018-04-02 11:09:57 -0700260 VLOG("Fail to read fromFd %d: %s", fromFd.get(), strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700261 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800262 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700263 } else if (amt == 0) {
Yi Jinea31cbe2018-04-02 11:09:57 -0700264 VLOG("Reached EOF of fromFd %d", fromFd.get());
Yi Jin0a3406f2017-06-22 19:23:11 -0700265 break;
266 } else {
Joe Onorato99598ee2019-02-11 15:55:13 +0000267 mBuffer->wp()->move(amt);
Yi Jin0a3406f2017-06-22 19:23:11 -0700268 }
269 }
270
271 mFinishTime = uptimeMillis();
272 return NO_ERROR;
273}
274
Joe Onorato99598ee2019-02-11 15:55:13 +0000275status_t FdBuffer::write(uint8_t const* buf, size_t size) {
276 return mBuffer->writeRaw(buf, size);
277}
Joe Onorato1754d742016-11-21 17:51:35 -0800278
Joe Onorato99598ee2019-02-11 15:55:13 +0000279status_t FdBuffer::write(const sp<ProtoReader>& reader) {
280 return mBuffer->writeRaw(reader);
281}
282
283status_t FdBuffer::write(const sp<ProtoReader>& reader, size_t size) {
284 return mBuffer->writeRaw(reader, size);
285}
286
287size_t FdBuffer::size() const {
288 return mBuffer->size();
289}
290
291sp<EncodedBuffer> FdBuffer::data() const {
292 return mBuffer;
293}
Yi Jin6cacbcb2018-03-30 14:04:52 -0700294
295} // namespace incidentd
296} // namespace os
297} // namespace android