blob: 35701446e9d94e87564809e1cf2492a1a6bbb801 [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 Jinb592e3b2018-02-01 15:17:04 -080029const ssize_t BUFFER_SIZE = 16 * 1024; // 16 KB
30const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
Joe Onorato1754d742016-11-21 17:51:35 -080031
Joe Onorato1754d742016-11-21 17:51:35 -080032FdBuffer::FdBuffer()
Yi Jinb592e3b2018-02-01 15:17:04 -080033 : mBuffer(BUFFER_SIZE), mStartTime(-1), mFinishTime(-1), mTimedOut(false), mTruncated(false) {}
Joe Onorato1754d742016-11-21 17:51:35 -080034
Yi Jinb592e3b2018-02-01 15:17:04 -080035FdBuffer::~FdBuffer() {}
Joe Onorato1754d742016-11-21 17:51:35 -080036
Yi Jinb592e3b2018-02-01 15:17:04 -080037status_t FdBuffer::read(int fd, int64_t timeout) {
38 struct pollfd pfds = {.fd = fd, .events = POLLIN};
Joe Onorato1754d742016-11-21 17:51:35 -080039 mStartTime = uptimeMillis();
40
41 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
42
Joe Onorato1754d742016-11-21 17:51:35 -080043 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -070044 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
45 mTruncated = true;
46 break;
Joe Onorato1754d742016-11-21 17:51:35 -080047 }
Yi Jinc23fad22017-09-15 17:24:59 -070048 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Joe Onorato1754d742016-11-21 17:51:35 -080049
50 int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
51 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080052 VLOG("timed out due to long read");
Joe Onorato1754d742016-11-21 17:51:35 -080053 mTimedOut = true;
54 break;
55 }
56
57 int count = poll(&pfds, 1, remainingTime);
58 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080059 VLOG("timed out due to block calling poll");
Joe Onorato1754d742016-11-21 17:51:35 -080060 mTimedOut = true;
61 break;
62 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080063 VLOG("poll failed: %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080064 return -errno;
65 } else {
66 if ((pfds.revents & POLLERR) != 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080067 VLOG("return event has error %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080068 return errno != 0 ? -errno : UNKNOWN_ERROR;
69 } else {
Yi Jinc23fad22017-09-15 17:24:59 -070070 ssize_t amt = ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Joe Onorato1754d742016-11-21 17:51:35 -080071 if (amt < 0) {
72 if (errno == EAGAIN || errno == EWOULDBLOCK) {
73 continue;
74 } else {
Yi Jinb592e3b2018-02-01 15:17:04 -080075 VLOG("Fail to read %d: %s", fd, strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080076 return -errno;
77 }
78 } else if (amt == 0) {
Yi Jin1a11fa12018-02-22 16:44:10 -080079 VLOG("Reached EOF of fd=%d", fd);
Joe Onorato1754d742016-11-21 17:51:35 -080080 break;
81 }
Yi Jinc23fad22017-09-15 17:24:59 -070082 mBuffer.wp()->move(amt);
Joe Onorato1754d742016-11-21 17:51:35 -080083 }
84 }
85 }
Joe Onorato1754d742016-11-21 17:51:35 -080086 mFinishTime = uptimeMillis();
87 return NO_ERROR;
88}
89
Kweku Adamseadd1232018-02-05 16:45:13 -080090status_t FdBuffer::readFully(int fd) {
91 mStartTime = uptimeMillis();
92
93 while (true) {
94 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
95 // Don't let it get too big.
96 mTruncated = true;
97 VLOG("Truncating data");
98 break;
99 }
100 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
101
102 ssize_t amt =
103 TEMP_FAILURE_RETRY(::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite()));
104 if (amt < 0) {
105 VLOG("Fail to read %d: %s", fd, strerror(errno));
106 return -errno;
107 } else if (amt == 0) {
108 VLOG("Done reading %zu bytes", mBuffer.size());
109 // We're done.
110 break;
111 }
112 mBuffer.wp()->move(amt);
113 }
114
115 mFinishTime = uptimeMillis();
116 return NO_ERROR;
117}
118
Yi Jinb592e3b2018-02-01 15:17:04 -0800119status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs,
120 const bool isSysfs) {
Yi Jin0a3406f2017-06-22 19:23:11 -0700121 struct pollfd pfds[] = {
Yi Jinb592e3b2018-02-01 15:17:04 -0800122 {.fd = fd, .events = POLLIN},
123 {.fd = toFd, .events = POLLOUT},
124 {.fd = fromFd, .events = POLLIN},
Yi Jin0a3406f2017-06-22 19:23:11 -0700125 };
126
127 mStartTime = uptimeMillis();
128
129 // mark all fds non blocking
130 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
131 fcntl(toFd, F_SETFL, fcntl(toFd, F_GETFL, 0) | O_NONBLOCK);
132 fcntl(fromFd, F_SETFL, fcntl(fromFd, F_GETFL, 0) | O_NONBLOCK);
133
134 // A circular buffer holds data read from fd and writes to parsing process
135 uint8_t cirBuf[BUFFER_SIZE];
136 size_t cirSize = 0;
137 int rpos = 0, wpos = 0;
138
139 // This is the buffer used to store processed data
Yi Jin0a3406f2017-06-22 19:23:11 -0700140 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -0700141 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
142 mTruncated = true;
143 break;
Yi Jin0a3406f2017-06-22 19:23:11 -0700144 }
Yi Jinc23fad22017-09-15 17:24:59 -0700145 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Yi Jin0a3406f2017-06-22 19:23:11 -0700146
147 int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
148 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800149 VLOG("timed out due to long read");
Yi Jin0a3406f2017-06-22 19:23:11 -0700150 mTimedOut = true;
151 break;
152 }
153
154 // wait for any pfds to be ready to perform IO
155 int count = poll(pfds, 3, remainingTime);
156 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800157 VLOG("timed out due to block calling poll");
Yi Jin0a3406f2017-06-22 19:23:11 -0700158 mTimedOut = true;
159 break;
160 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800161 VLOG("Fail to poll: %s", strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700162 return -errno;
163 }
164
165 // make sure no errors occur on any fds
166 for (int i = 0; i < 3; ++i) {
167 if ((pfds[i].revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800168 if (i == 0 && isSysfs) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800169 VLOG("fd %d is sysfs, ignore its POLLERR return value", fd);
Yi Jin0eb22342017-11-06 17:17:27 -0800170 continue;
171 }
Yi Jinb592e3b2018-02-01 15:17:04 -0800172 VLOG("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700173 return errno != 0 ? -errno : UNKNOWN_ERROR;
174 }
175 }
176
177 // read from fd
178 if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
179 ssize_t amt;
180 if (rpos >= wpos) {
181 amt = ::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos);
182 } else {
Yi Jin0ed9b682017-08-18 14:51:20 -0700183 amt = ::read(fd, cirBuf + rpos, wpos - rpos);
Yi Jin0a3406f2017-06-22 19:23:11 -0700184 }
185 if (amt < 0) {
186 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800187 VLOG("Fail to read fd %d: %s", fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700188 return -errno;
Yi Jin1a11fa12018-02-22 16:44:10 -0800189 } // otherwise just continue
190 } else if (amt == 0) {
191 VLOG("Reached EOF of input file %d", fd);
192 pfds[0].fd = -1; // reach EOF so don't have to poll pfds[0].
Yi Jin0a3406f2017-06-22 19:23:11 -0700193 } else {
194 rpos += amt;
195 cirSize += amt;
196 }
197 }
198
199 // write to parsing process
200 if (cirSize > 0 && pfds[1].fd != -1) {
201 ssize_t amt;
202 if (rpos > wpos) {
203 amt = ::write(toFd, cirBuf + wpos, rpos - wpos);
204 } else {
205 amt = ::write(toFd, cirBuf + wpos, BUFFER_SIZE - wpos);
206 }
207 if (amt < 0) {
208 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800209 VLOG("Fail to write toFd %d: %s", toFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700210 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800211 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700212 } else {
213 wpos += amt;
214 cirSize -= amt;
215 }
216 }
217
218 // if buffer is empty and fd is closed, close write fd.
219 if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
Yi Jin1a11fa12018-02-22 16:44:10 -0800220 VLOG("Close write pipe %d", toFd);
Yi Jin0a3406f2017-06-22 19:23:11 -0700221 ::close(pfds[1].fd);
222 pfds[1].fd = -1;
223 }
224
225 // circular buffer, reset rpos and wpos
226 if (rpos >= BUFFER_SIZE) {
227 rpos = 0;
228 }
229 if (wpos >= BUFFER_SIZE) {
230 wpos = 0;
231 }
232
233 // read from parsing process
Yi Jinc23fad22017-09-15 17:24:59 -0700234 ssize_t amt = ::read(fromFd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Yi Jin0a3406f2017-06-22 19:23:11 -0700235 if (amt < 0) {
236 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800237 VLOG("Fail to read fromFd %d: %s", fromFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700238 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800239 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700240 } else if (amt == 0) {
Yi Jin1a11fa12018-02-22 16:44:10 -0800241 VLOG("Reached EOF of fromFd %d", fromFd);
Yi Jin0a3406f2017-06-22 19:23:11 -0700242 break;
243 } else {
Yi Jinc23fad22017-09-15 17:24:59 -0700244 mBuffer.wp()->move(amt);
Yi Jin0a3406f2017-06-22 19:23:11 -0700245 }
246 }
247
248 mFinishTime = uptimeMillis();
249 return NO_ERROR;
250}
251
Yi Jinb592e3b2018-02-01 15:17:04 -0800252size_t FdBuffer::size() const { return mBuffer.size(); }
Joe Onorato1754d742016-11-21 17:51:35 -0800253
Yi Jinb592e3b2018-02-01 15:17:04 -0800254EncodedBuffer::iterator FdBuffer::data() const { return mBuffer.begin(); }