blob: 78c322edcccc403e565aaec2863e8c27eedc6e95 [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"
Mike Ma892ccd92020-03-20 16:30:37 -070020#include "incidentd_util.h"
Joe Onorato1754d742016-11-21 17:51:35 -080021
Mike Ma35056662018-12-06 13:32:59 -080022#include <log/log.h>
Joe Onorato1754d742016-11-21 17:51:35 -080023#include <utils/SystemClock.h>
24
25#include <fcntl.h>
26#include <poll.h>
27#include <unistd.h>
Yi Jin0a3406f2017-06-22 19:23:11 -070028#include <wait.h>
Joe Onorato1754d742016-11-21 17:51:35 -080029
Yi Jin6cacbcb2018-03-30 14:04:52 -070030namespace android {
31namespace os {
32namespace incidentd {
33
Yi Jinb592e3b2018-02-01 15:17:04 -080034const ssize_t BUFFER_SIZE = 16 * 1024; // 16 KB
Mike Ma892ccd92020-03-20 16:30:37 -070035const ssize_t MAX_BUFFER_SIZE = 96 * 1024 * 1024; // 96 MB
Joe Onorato1754d742016-11-21 17:51:35 -080036
Mike Ma892ccd92020-03-20 16:30:37 -070037FdBuffer::FdBuffer(): FdBuffer(get_buffer_from_pool(), /* isBufferPooled= */ true) {
38}
39
40FdBuffer::FdBuffer(sp<EncodedBuffer> buffer, bool isBufferPooled)
41 :mBuffer(buffer),
Joe Onorato99598ee2019-02-11 15:55:13 +000042 mStartTime(-1),
43 mFinishTime(-1),
44 mTimedOut(false),
Mike Ma892ccd92020-03-20 16:30:37 -070045 mTruncated(false),
46 mIsBufferPooled(isBufferPooled) {
Joe Onorato99598ee2019-02-11 15:55:13 +000047}
Joe Onorato1754d742016-11-21 17:51:35 -080048
Joe Onorato99598ee2019-02-11 15:55:13 +000049FdBuffer::~FdBuffer() {
Mike Ma892ccd92020-03-20 16:30:37 -070050 if (mIsBufferPooled) {
51 return_buffer_to_pool(mBuffer);
52 }
Joe Onorato99598ee2019-02-11 15:55:13 +000053}
Joe Onorato1754d742016-11-21 17:51:35 -080054
Yi Jine3dab2d2018-03-22 16:56:39 -070055status_t FdBuffer::read(int fd, int64_t timeout) {
56 struct pollfd pfds = {.fd = fd, .events = POLLIN};
Joe Onorato1754d742016-11-21 17:51:35 -080057 mStartTime = uptimeMillis();
58
Yi Jine3dab2d2018-03-22 16:56:39 -070059 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
Joe Onorato1754d742016-11-21 17:51:35 -080060
Joe Onorato1754d742016-11-21 17:51:35 -080061 while (true) {
Mike Ma892ccd92020-03-20 16:30:37 -070062 if (mBuffer->size() >= MAX_BUFFER_SIZE) {
Yi Jinc23fad22017-09-15 17:24:59 -070063 mTruncated = true;
Mike Ma28381692018-12-04 15:46:29 -080064 VLOG("Truncating data");
Yi Jinc23fad22017-09-15 17:24:59 -070065 break;
Joe Onorato1754d742016-11-21 17:51:35 -080066 }
Joe Onorato99598ee2019-02-11 15:55:13 +000067 if (mBuffer->writeBuffer() == NULL) {
Mike Ma28381692018-12-04 15:46:29 -080068 VLOG("No memory");
69 return NO_MEMORY;
70 }
Joe Onorato1754d742016-11-21 17:51:35 -080071
72 int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
73 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080074 VLOG("timed out due to long read");
Joe Onorato1754d742016-11-21 17:51:35 -080075 mTimedOut = true;
76 break;
77 }
78
Mike Ma28381692018-12-04 15:46:29 -080079 int count = TEMP_FAILURE_RETRY(poll(&pfds, 1, remainingTime));
Joe Onorato1754d742016-11-21 17:51:35 -080080 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080081 VLOG("timed out due to block calling poll");
Joe Onorato1754d742016-11-21 17:51:35 -080082 mTimedOut = true;
83 break;
84 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080085 VLOG("poll failed: %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080086 return -errno;
87 } else {
88 if ((pfds.revents & POLLERR) != 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080089 VLOG("return event has error %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080090 return errno != 0 ? -errno : UNKNOWN_ERROR;
91 } else {
Yi Jin0e5d5772018-04-20 11:16:10 -070092 ssize_t amt = TEMP_FAILURE_RETRY(
Joe Onorato99598ee2019-02-11 15:55:13 +000093 ::read(fd, mBuffer->writeBuffer(), mBuffer->currentToWrite()));
Joe Onorato1754d742016-11-21 17:51:35 -080094 if (amt < 0) {
95 if (errno == EAGAIN || errno == EWOULDBLOCK) {
96 continue;
97 } else {
Yi Jine3dab2d2018-03-22 16:56:39 -070098 VLOG("Fail to read %d: %s", fd, strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080099 return -errno;
100 }
101 } else if (amt == 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700102 VLOG("Reached EOF of fd=%d", fd);
Joe Onorato1754d742016-11-21 17:51:35 -0800103 break;
104 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000105 mBuffer->wp()->move(amt);
Joe Onorato1754d742016-11-21 17:51:35 -0800106 }
107 }
108 }
Joe Onorato1754d742016-11-21 17:51:35 -0800109 mFinishTime = uptimeMillis();
110 return NO_ERROR;
111}
112
Yi Jine3dab2d2018-03-22 16:56:39 -0700113status_t FdBuffer::readFully(int fd) {
Kweku Adamseadd1232018-02-05 16:45:13 -0800114 mStartTime = uptimeMillis();
115
116 while (true) {
Mike Ma892ccd92020-03-20 16:30:37 -0700117 if (mBuffer->size() >= MAX_BUFFER_SIZE) {
Kweku Adamseadd1232018-02-05 16:45:13 -0800118 // Don't let it get too big.
119 mTruncated = true;
120 VLOG("Truncating data");
121 break;
122 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000123 if (mBuffer->writeBuffer() == NULL) {
Mike Ma28381692018-12-04 15:46:29 -0800124 VLOG("No memory");
125 return NO_MEMORY;
126 }
Kweku Adamseadd1232018-02-05 16:45:13 -0800127
Yi Jine3dab2d2018-03-22 16:56:39 -0700128 ssize_t amt =
Joe Onorato99598ee2019-02-11 15:55:13 +0000129 TEMP_FAILURE_RETRY(::read(fd, mBuffer->writeBuffer(), mBuffer->currentToWrite()));
Kweku Adamseadd1232018-02-05 16:45:13 -0800130 if (amt < 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700131 VLOG("Fail to read %d: %s", fd, strerror(errno));
Kweku Adamseadd1232018-02-05 16:45:13 -0800132 return -errno;
133 } else if (amt == 0) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000134 VLOG("Done reading %zu bytes", mBuffer->size());
Kweku Adamseadd1232018-02-05 16:45:13 -0800135 // We're done.
136 break;
137 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000138 mBuffer->wp()->move(amt);
Kweku Adamseadd1232018-02-05 16:45:13 -0800139 }
140
141 mFinishTime = uptimeMillis();
142 return NO_ERROR;
143}
144
Yi Jine3dab2d2018-03-22 16:56:39 -0700145status_t FdBuffer::readProcessedDataInStream(int fd, unique_fd toFd, unique_fd fromFd,
Yi Jin6355d2f2018-03-14 15:18:02 -0700146 int64_t timeoutMs, const bool isSysfs) {
Yi Jin0a3406f2017-06-22 19:23:11 -0700147 struct pollfd pfds[] = {
Yi Jine3dab2d2018-03-22 16:56:39 -0700148 {.fd = fd, .events = POLLIN},
149 {.fd = toFd.get(), .events = POLLOUT},
150 {.fd = fromFd.get(), .events = POLLIN},
Yi Jin0a3406f2017-06-22 19:23:11 -0700151 };
152
153 mStartTime = uptimeMillis();
154
155 // mark all fds non blocking
Yi Jine3dab2d2018-03-22 16:56:39 -0700156 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
157 fcntl(toFd.get(), F_SETFL, fcntl(toFd.get(), F_GETFL, 0) | O_NONBLOCK);
158 fcntl(fromFd.get(), F_SETFL, fcntl(fromFd.get(), F_GETFL, 0) | O_NONBLOCK);
Yi Jin0a3406f2017-06-22 19:23:11 -0700159
160 // A circular buffer holds data read from fd and writes to parsing process
161 uint8_t cirBuf[BUFFER_SIZE];
162 size_t cirSize = 0;
163 int rpos = 0, wpos = 0;
164
165 // This is the buffer used to store processed data
Yi Jin0a3406f2017-06-22 19:23:11 -0700166 while (true) {
Mike Ma892ccd92020-03-20 16:30:37 -0700167 if (mBuffer->size() >= MAX_BUFFER_SIZE) {
Mike Ma28381692018-12-04 15:46:29 -0800168 VLOG("Truncating data");
Yi Jinc23fad22017-09-15 17:24:59 -0700169 mTruncated = true;
170 break;
Yi Jin0a3406f2017-06-22 19:23:11 -0700171 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000172 if (mBuffer->writeBuffer() == NULL) {
Mike Ma28381692018-12-04 15:46:29 -0800173 VLOG("No memory");
174 return NO_MEMORY;
175 }
Yi Jin0a3406f2017-06-22 19:23:11 -0700176
177 int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
178 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800179 VLOG("timed out due to long read");
Yi Jin0a3406f2017-06-22 19:23:11 -0700180 mTimedOut = true;
181 break;
182 }
183
184 // wait for any pfds to be ready to perform IO
Mike Ma28381692018-12-04 15:46:29 -0800185 int count = TEMP_FAILURE_RETRY(poll(pfds, 3, remainingTime));
Yi Jin0a3406f2017-06-22 19:23:11 -0700186 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800187 VLOG("timed out due to block calling poll");
Yi Jin0a3406f2017-06-22 19:23:11 -0700188 mTimedOut = true;
189 break;
190 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800191 VLOG("Fail to poll: %s", strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700192 return -errno;
193 }
194
195 // make sure no errors occur on any fds
196 for (int i = 0; i < 3; ++i) {
197 if ((pfds[i].revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800198 if (i == 0 && isSysfs) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700199 VLOG("fd %d is sysfs, ignore its POLLERR return value", fd);
Yi Jin0eb22342017-11-06 17:17:27 -0800200 continue;
201 }
Yi Jine3dab2d2018-03-22 16:56:39 -0700202 VLOG("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700203 return errno != 0 ? -errno : UNKNOWN_ERROR;
204 }
205 }
206
207 // read from fd
208 if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
209 ssize_t amt;
210 if (rpos >= wpos) {
Yi Jin0e5d5772018-04-20 11:16:10 -0700211 amt = TEMP_FAILURE_RETRY(::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700212 } else {
Yi Jin0e5d5772018-04-20 11:16:10 -0700213 amt = TEMP_FAILURE_RETRY(::read(fd, cirBuf + rpos, wpos - rpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700214 }
215 if (amt < 0) {
216 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700217 VLOG("Fail to read fd %d: %s", fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700218 return -errno;
Yi Jin1a11fa12018-02-22 16:44:10 -0800219 } // otherwise just continue
220 } else if (amt == 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700221 VLOG("Reached EOF of input file %d", fd);
Yi Jin1a11fa12018-02-22 16:44:10 -0800222 pfds[0].fd = -1; // reach EOF so don't have to poll pfds[0].
Yi Jin0a3406f2017-06-22 19:23:11 -0700223 } else {
224 rpos += amt;
225 cirSize += amt;
226 }
227 }
228
229 // write to parsing process
230 if (cirSize > 0 && pfds[1].fd != -1) {
231 ssize_t amt;
232 if (rpos > wpos) {
Yi Jin0e5d5772018-04-20 11:16:10 -0700233 amt = TEMP_FAILURE_RETRY(::write(toFd.get(), cirBuf + wpos, rpos - wpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700234 } else {
Yi Jin0e5d5772018-04-20 11:16:10 -0700235 amt = TEMP_FAILURE_RETRY(::write(toFd.get(), cirBuf + wpos, BUFFER_SIZE - wpos));
Yi Jin0a3406f2017-06-22 19:23:11 -0700236 }
237 if (amt < 0) {
238 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jin6cacbcb2018-03-30 14:04:52 -0700239 VLOG("Fail to write toFd %d: %s", toFd.get(), strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700240 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800241 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700242 } else {
243 wpos += amt;
244 cirSize -= amt;
245 }
246 }
247
248 // if buffer is empty and fd is closed, close write fd.
249 if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700250 VLOG("Close write pipe %d", toFd.get());
251 toFd.reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700252 pfds[1].fd = -1;
253 }
254
255 // circular buffer, reset rpos and wpos
256 if (rpos >= BUFFER_SIZE) {
257 rpos = 0;
258 }
259 if (wpos >= BUFFER_SIZE) {
260 wpos = 0;
261 }
262
263 // read from parsing process
Yi Jin0e5d5772018-04-20 11:16:10 -0700264 ssize_t amt = TEMP_FAILURE_RETRY(
Joe Onorato99598ee2019-02-11 15:55:13 +0000265 ::read(fromFd.get(), mBuffer->writeBuffer(), mBuffer->currentToWrite()));
Yi Jin0a3406f2017-06-22 19:23:11 -0700266 if (amt < 0) {
267 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinea31cbe2018-04-02 11:09:57 -0700268 VLOG("Fail to read fromFd %d: %s", fromFd.get(), strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700269 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800270 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700271 } else if (amt == 0) {
Yi Jinea31cbe2018-04-02 11:09:57 -0700272 VLOG("Reached EOF of fromFd %d", fromFd.get());
Yi Jin0a3406f2017-06-22 19:23:11 -0700273 break;
274 } else {
Joe Onorato99598ee2019-02-11 15:55:13 +0000275 mBuffer->wp()->move(amt);
Yi Jin0a3406f2017-06-22 19:23:11 -0700276 }
277 }
278
279 mFinishTime = uptimeMillis();
280 return NO_ERROR;
281}
282
Joe Onorato99598ee2019-02-11 15:55:13 +0000283status_t FdBuffer::write(uint8_t const* buf, size_t size) {
284 return mBuffer->writeRaw(buf, size);
285}
Joe Onorato1754d742016-11-21 17:51:35 -0800286
Joe Onorato99598ee2019-02-11 15:55:13 +0000287status_t FdBuffer::write(const sp<ProtoReader>& reader) {
288 return mBuffer->writeRaw(reader);
289}
290
291status_t FdBuffer::write(const sp<ProtoReader>& reader, size_t size) {
292 return mBuffer->writeRaw(reader, size);
293}
294
295size_t FdBuffer::size() const {
296 return mBuffer->size();
297}
298
299sp<EncodedBuffer> FdBuffer::data() const {
300 return mBuffer;
301}
Yi Jin6cacbcb2018-03-30 14:04:52 -0700302
303} // namespace incidentd
304} // namespace os
305} // namespace android