blob: 64da6773686a5880347aba5b46cee69b94718098 [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
Yi Jinb592e3b2018-02-01 15:17:04 -080090status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs,
91 const bool isSysfs) {
Yi Jin0a3406f2017-06-22 19:23:11 -070092 struct pollfd pfds[] = {
Yi Jinb592e3b2018-02-01 15:17:04 -080093 {.fd = fd, .events = POLLIN},
94 {.fd = toFd, .events = POLLOUT},
95 {.fd = fromFd, .events = POLLIN},
Yi Jin0a3406f2017-06-22 19:23:11 -070096 };
97
98 mStartTime = uptimeMillis();
99
100 // mark all fds non blocking
101 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
102 fcntl(toFd, F_SETFL, fcntl(toFd, F_GETFL, 0) | O_NONBLOCK);
103 fcntl(fromFd, F_SETFL, fcntl(fromFd, F_GETFL, 0) | O_NONBLOCK);
104
105 // A circular buffer holds data read from fd and writes to parsing process
106 uint8_t cirBuf[BUFFER_SIZE];
107 size_t cirSize = 0;
108 int rpos = 0, wpos = 0;
109
110 // This is the buffer used to store processed data
Yi Jin0a3406f2017-06-22 19:23:11 -0700111 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -0700112 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
113 mTruncated = true;
114 break;
Yi Jin0a3406f2017-06-22 19:23:11 -0700115 }
Yi Jinc23fad22017-09-15 17:24:59 -0700116 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Yi Jin0a3406f2017-06-22 19:23:11 -0700117
118 int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
119 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800120 VLOG("timed out due to long read");
Yi Jin0a3406f2017-06-22 19:23:11 -0700121 mTimedOut = true;
122 break;
123 }
124
125 // wait for any pfds to be ready to perform IO
126 int count = poll(pfds, 3, remainingTime);
127 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800128 VLOG("timed out due to block calling poll");
Yi Jin0a3406f2017-06-22 19:23:11 -0700129 mTimedOut = true;
130 break;
131 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800132 VLOG("Fail to poll: %s", strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700133 return -errno;
134 }
135
136 // make sure no errors occur on any fds
137 for (int i = 0; i < 3; ++i) {
138 if ((pfds[i].revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800139 if (i == 0 && isSysfs) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800140 VLOG("fd %d is sysfs, ignore its POLLERR return value", fd);
Yi Jin0eb22342017-11-06 17:17:27 -0800141 continue;
142 }
Yi Jinb592e3b2018-02-01 15:17:04 -0800143 VLOG("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700144 return errno != 0 ? -errno : UNKNOWN_ERROR;
145 }
146 }
147
148 // read from fd
149 if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
150 ssize_t amt;
151 if (rpos >= wpos) {
152 amt = ::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos);
153 } else {
Yi Jin0ed9b682017-08-18 14:51:20 -0700154 amt = ::read(fd, cirBuf + rpos, wpos - rpos);
Yi Jin0a3406f2017-06-22 19:23:11 -0700155 }
156 if (amt < 0) {
157 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800158 VLOG("Fail to read fd %d: %s", fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700159 return -errno;
Yi Jin1a11fa12018-02-22 16:44:10 -0800160 } // otherwise just continue
161 } else if (amt == 0) {
162 VLOG("Reached EOF of input file %d", fd);
163 pfds[0].fd = -1; // reach EOF so don't have to poll pfds[0].
Yi Jin0a3406f2017-06-22 19:23:11 -0700164 } else {
165 rpos += amt;
166 cirSize += amt;
167 }
168 }
169
170 // write to parsing process
171 if (cirSize > 0 && pfds[1].fd != -1) {
172 ssize_t amt;
173 if (rpos > wpos) {
174 amt = ::write(toFd, cirBuf + wpos, rpos - wpos);
175 } else {
176 amt = ::write(toFd, cirBuf + wpos, BUFFER_SIZE - wpos);
177 }
178 if (amt < 0) {
179 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800180 VLOG("Fail to write toFd %d: %s", toFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700181 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800182 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700183 } else {
184 wpos += amt;
185 cirSize -= amt;
186 }
187 }
188
189 // if buffer is empty and fd is closed, close write fd.
190 if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
Yi Jin1a11fa12018-02-22 16:44:10 -0800191 VLOG("Close write pipe %d", toFd);
Yi Jin0a3406f2017-06-22 19:23:11 -0700192 ::close(pfds[1].fd);
193 pfds[1].fd = -1;
194 }
195
196 // circular buffer, reset rpos and wpos
197 if (rpos >= BUFFER_SIZE) {
198 rpos = 0;
199 }
200 if (wpos >= BUFFER_SIZE) {
201 wpos = 0;
202 }
203
204 // read from parsing process
Yi Jinc23fad22017-09-15 17:24:59 -0700205 ssize_t amt = ::read(fromFd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Yi Jin0a3406f2017-06-22 19:23:11 -0700206 if (amt < 0) {
207 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800208 VLOG("Fail to read fromFd %d: %s", fromFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700209 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800210 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700211 } else if (amt == 0) {
Yi Jin1a11fa12018-02-22 16:44:10 -0800212 VLOG("Reached EOF of fromFd %d", fromFd);
Yi Jin0a3406f2017-06-22 19:23:11 -0700213 break;
214 } else {
Yi Jinc23fad22017-09-15 17:24:59 -0700215 mBuffer.wp()->move(amt);
Yi Jin0a3406f2017-06-22 19:23:11 -0700216 }
217 }
218
219 mFinishTime = uptimeMillis();
220 return NO_ERROR;
221}
222
Yi Jinb592e3b2018-02-01 15:17:04 -0800223size_t FdBuffer::size() const { return mBuffer.size(); }
Joe Onorato1754d742016-11-21 17:51:35 -0800224
Yi Jinb592e3b2018-02-01 15:17:04 -0800225EncodedBuffer::iterator FdBuffer::data() const { return mBuffer.begin(); }