blob: 86c2e206ef969618e6f556a9b1c2b48bb956a105 [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
21#include <cutils/log.h>
22#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;
50 break;
Joe Onorato1754d742016-11-21 17:51:35 -080051 }
Yi Jinc23fad22017-09-15 17:24:59 -070052 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Joe Onorato1754d742016-11-21 17:51:35 -080053
54 int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
55 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080056 VLOG("timed out due to long read");
Joe Onorato1754d742016-11-21 17:51:35 -080057 mTimedOut = true;
58 break;
59 }
60
61 int count = poll(&pfds, 1, remainingTime);
62 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080063 VLOG("timed out due to block calling poll");
Joe Onorato1754d742016-11-21 17:51:35 -080064 mTimedOut = true;
65 break;
66 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080067 VLOG("poll failed: %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080068 return -errno;
69 } else {
70 if ((pfds.revents & POLLERR) != 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080071 VLOG("return event has error %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080072 return errno != 0 ? -errno : UNKNOWN_ERROR;
73 } else {
Yi Jine3dab2d2018-03-22 16:56:39 -070074 ssize_t amt = ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Joe Onorato1754d742016-11-21 17:51:35 -080075 if (amt < 0) {
76 if (errno == EAGAIN || errno == EWOULDBLOCK) {
77 continue;
78 } else {
Yi Jine3dab2d2018-03-22 16:56:39 -070079 VLOG("Fail to read %d: %s", fd, strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080080 return -errno;
81 }
82 } else if (amt == 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -070083 VLOG("Reached EOF of fd=%d", fd);
Joe Onorato1754d742016-11-21 17:51:35 -080084 break;
85 }
Yi Jinc23fad22017-09-15 17:24:59 -070086 mBuffer.wp()->move(amt);
Joe Onorato1754d742016-11-21 17:51:35 -080087 }
88 }
89 }
Joe Onorato1754d742016-11-21 17:51:35 -080090 mFinishTime = uptimeMillis();
91 return NO_ERROR;
92}
93
Yi Jine3dab2d2018-03-22 16:56:39 -070094status_t FdBuffer::readFully(int fd) {
Kweku Adamseadd1232018-02-05 16:45:13 -080095 mStartTime = uptimeMillis();
96
97 while (true) {
98 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
99 // Don't let it get too big.
100 mTruncated = true;
101 VLOG("Truncating data");
102 break;
103 }
104 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
105
Yi Jine3dab2d2018-03-22 16:56:39 -0700106 ssize_t amt =
107 TEMP_FAILURE_RETRY(::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite()));
Kweku Adamseadd1232018-02-05 16:45:13 -0800108 if (amt < 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700109 VLOG("Fail to read %d: %s", fd, strerror(errno));
Kweku Adamseadd1232018-02-05 16:45:13 -0800110 return -errno;
111 } else if (amt == 0) {
112 VLOG("Done reading %zu bytes", mBuffer.size());
113 // We're done.
114 break;
115 }
116 mBuffer.wp()->move(amt);
117 }
118
119 mFinishTime = uptimeMillis();
120 return NO_ERROR;
121}
122
Yi Jine3dab2d2018-03-22 16:56:39 -0700123status_t FdBuffer::readProcessedDataInStream(int fd, unique_fd toFd, unique_fd fromFd,
Yi Jin6355d2f2018-03-14 15:18:02 -0700124 int64_t timeoutMs, const bool isSysfs) {
Yi Jin0a3406f2017-06-22 19:23:11 -0700125 struct pollfd pfds[] = {
Yi Jine3dab2d2018-03-22 16:56:39 -0700126 {.fd = fd, .events = POLLIN},
127 {.fd = toFd.get(), .events = POLLOUT},
128 {.fd = fromFd.get(), .events = POLLIN},
Yi Jin0a3406f2017-06-22 19:23:11 -0700129 };
130
131 mStartTime = uptimeMillis();
132
133 // mark all fds non blocking
Yi Jine3dab2d2018-03-22 16:56:39 -0700134 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
135 fcntl(toFd.get(), F_SETFL, fcntl(toFd.get(), F_GETFL, 0) | O_NONBLOCK);
136 fcntl(fromFd.get(), F_SETFL, fcntl(fromFd.get(), F_GETFL, 0) | O_NONBLOCK);
Yi Jin0a3406f2017-06-22 19:23:11 -0700137
138 // A circular buffer holds data read from fd and writes to parsing process
139 uint8_t cirBuf[BUFFER_SIZE];
140 size_t cirSize = 0;
141 int rpos = 0, wpos = 0;
142
143 // This is the buffer used to store processed data
Yi Jin0a3406f2017-06-22 19:23:11 -0700144 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -0700145 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
146 mTruncated = true;
147 break;
Yi Jin0a3406f2017-06-22 19:23:11 -0700148 }
Yi Jinc23fad22017-09-15 17:24:59 -0700149 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Yi Jin0a3406f2017-06-22 19:23:11 -0700150
151 int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
152 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800153 VLOG("timed out due to long read");
Yi Jin0a3406f2017-06-22 19:23:11 -0700154 mTimedOut = true;
155 break;
156 }
157
158 // wait for any pfds to be ready to perform IO
159 int count = poll(pfds, 3, remainingTime);
160 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800161 VLOG("timed out due to block calling poll");
Yi Jin0a3406f2017-06-22 19:23:11 -0700162 mTimedOut = true;
163 break;
164 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800165 VLOG("Fail to poll: %s", strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700166 return -errno;
167 }
168
169 // make sure no errors occur on any fds
170 for (int i = 0; i < 3; ++i) {
171 if ((pfds[i].revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800172 if (i == 0 && isSysfs) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700173 VLOG("fd %d is sysfs, ignore its POLLERR return value", fd);
Yi Jin0eb22342017-11-06 17:17:27 -0800174 continue;
175 }
Yi Jine3dab2d2018-03-22 16:56:39 -0700176 VLOG("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700177 return errno != 0 ? -errno : UNKNOWN_ERROR;
178 }
179 }
180
181 // read from fd
182 if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
183 ssize_t amt;
184 if (rpos >= wpos) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700185 amt = ::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos);
Yi Jin0a3406f2017-06-22 19:23:11 -0700186 } else {
Yi Jine3dab2d2018-03-22 16:56:39 -0700187 amt = ::read(fd, cirBuf + rpos, wpos - rpos);
Yi Jin0a3406f2017-06-22 19:23:11 -0700188 }
189 if (amt < 0) {
190 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700191 VLOG("Fail to read fd %d: %s", fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700192 return -errno;
Yi Jin1a11fa12018-02-22 16:44:10 -0800193 } // otherwise just continue
194 } else if (amt == 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700195 VLOG("Reached EOF of input file %d", fd);
Yi Jin1a11fa12018-02-22 16:44:10 -0800196 pfds[0].fd = -1; // reach EOF so don't have to poll pfds[0].
Yi Jin0a3406f2017-06-22 19:23:11 -0700197 } else {
198 rpos += amt;
199 cirSize += amt;
200 }
201 }
202
203 // write to parsing process
204 if (cirSize > 0 && pfds[1].fd != -1) {
205 ssize_t amt;
206 if (rpos > wpos) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700207 amt = ::write(toFd.get(), cirBuf + wpos, rpos - wpos);
Yi Jin0a3406f2017-06-22 19:23:11 -0700208 } else {
Yi Jine3dab2d2018-03-22 16:56:39 -0700209 amt = ::write(toFd.get(), cirBuf + wpos, BUFFER_SIZE - wpos);
Yi Jin0a3406f2017-06-22 19:23:11 -0700210 }
211 if (amt < 0) {
212 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jin6cacbcb2018-03-30 14:04:52 -0700213 VLOG("Fail to write toFd %d: %s", toFd.get(), strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700214 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800215 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700216 } else {
217 wpos += amt;
218 cirSize -= amt;
219 }
220 }
221
222 // if buffer is empty and fd is closed, close write fd.
223 if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700224 VLOG("Close write pipe %d", toFd.get());
225 toFd.reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700226 pfds[1].fd = -1;
227 }
228
229 // circular buffer, reset rpos and wpos
230 if (rpos >= BUFFER_SIZE) {
231 rpos = 0;
232 }
233 if (wpos >= BUFFER_SIZE) {
234 wpos = 0;
235 }
236
237 // read from parsing process
Yi Jine3dab2d2018-03-22 16:56:39 -0700238 ssize_t amt = ::read(fromFd.get(), mBuffer.writeBuffer(), mBuffer.currentToWrite());
Yi Jin0a3406f2017-06-22 19:23:11 -0700239 if (amt < 0) {
240 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700241 VLOG("Fail to read fromFd.get() %d: %s", fromFd.get(), strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700242 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800243 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700244 } else if (amt == 0) {
Yi Jine3dab2d2018-03-22 16:56:39 -0700245 VLOG("Reached EOF of fromFd.get() %d", fromFd.get());
Yi Jin0a3406f2017-06-22 19:23:11 -0700246 break;
247 } else {
Yi Jinc23fad22017-09-15 17:24:59 -0700248 mBuffer.wp()->move(amt);
Yi Jin0a3406f2017-06-22 19:23:11 -0700249 }
250 }
251
252 mFinishTime = uptimeMillis();
253 return NO_ERROR;
254}
255
Yi Jinb592e3b2018-02-01 15:17:04 -0800256size_t FdBuffer::size() const { return mBuffer.size(); }
Joe Onorato1754d742016-11-21 17:51:35 -0800257
Yi Jinb592e3b2018-02-01 15:17:04 -0800258EncodedBuffer::iterator FdBuffer::data() const { return mBuffer.begin(); }
Yi Jin6cacbcb2018-03-30 14:04:52 -0700259
260} // namespace incidentd
261} // namespace os
262} // namespace android