OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/sync_socket.h" | 5 #include "base/sync_socket.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <limits.h> | 9 #include <limits.h> |
| 10 #include <poll.h> |
10 #include <stddef.h> | 11 #include <stddef.h> |
11 #include <stdio.h> | 12 #include <stdio.h> |
12 #include <sys/ioctl.h> | 13 #include <sys/ioctl.h> |
13 #include <sys/socket.h> | 14 #include <sys/socket.h> |
14 #include <sys/types.h> | 15 #include <sys/types.h> |
15 | 16 |
16 #if defined(OS_SOLARIS) | 17 #if defined(OS_SOLARIS) |
17 #include <sys/filio.h> | 18 #include <sys/filio.h> |
18 #endif | 19 #endif |
19 | 20 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 } | 136 } |
136 | 137 |
137 size_t SyncSocket::ReceiveWithTimeout(void* buffer, | 138 size_t SyncSocket::ReceiveWithTimeout(void* buffer, |
138 size_t length, | 139 size_t length, |
139 TimeDelta timeout) { | 140 TimeDelta timeout) { |
140 ThreadRestrictions::AssertIOAllowed(); | 141 ThreadRestrictions::AssertIOAllowed(); |
141 DCHECK_GT(length, 0u); | 142 DCHECK_GT(length, 0u); |
142 DCHECK_LE(length, kMaxMessageLength); | 143 DCHECK_LE(length, kMaxMessageLength); |
143 DCHECK_NE(handle_, kInvalidHandle); | 144 DCHECK_NE(handle_, kInvalidHandle); |
144 | 145 |
145 // TODO(dalecurtis): There's an undiagnosed issue on OSX where we're seeing | |
146 // large numbers of open files which prevents select() from being used. In | |
147 // this case, the best we can do is Peek() to see if we can Receive() now or | |
148 // return a timeout error (0) if not. See http://crbug.com/314364. | |
149 if (handle_ >= FD_SETSIZE) | |
150 return Peek() < length ? 0 : Receive(buffer, length); | |
151 | |
152 // Only timeouts greater than zero and less than one second are allowed. | 146 // Only timeouts greater than zero and less than one second are allowed. |
153 DCHECK_GT(timeout.InMicroseconds(), 0); | 147 DCHECK_GT(timeout.InMicroseconds(), 0); |
154 DCHECK_LT(timeout.InMicroseconds(), | 148 DCHECK_LT(timeout.InMicroseconds(), |
155 base::TimeDelta::FromSeconds(1).InMicroseconds()); | 149 TimeDelta::FromSeconds(1).InMicroseconds()); |
156 | 150 |
157 // Track the start time so we can reduce the timeout as data is read. | 151 // Track the start time so we can reduce the timeout as data is read. |
158 TimeTicks start_time = TimeTicks::Now(); | 152 TimeTicks start_time = TimeTicks::Now(); |
159 const TimeTicks finish_time = start_time + timeout; | 153 const TimeTicks finish_time = start_time + timeout; |
160 | 154 |
161 fd_set read_fds; | 155 struct pollfd pollfd; |
162 size_t bytes_read_total; | 156 pollfd.fd = handle_; |
163 for (bytes_read_total = 0; | 157 pollfd.events = POLLIN; |
164 bytes_read_total < length && timeout.InMicroseconds() > 0; | 158 pollfd.revents = 0; |
165 timeout = finish_time - base::TimeTicks::Now()) { | |
166 FD_ZERO(&read_fds); | |
167 FD_SET(handle_, &read_fds); | |
168 | 159 |
169 // Wait for data to become available. | 160 size_t bytes_read_total = 0; |
170 struct timeval timeout_struct = | 161 while (bytes_read_total < length) { |
171 { 0, static_cast<suseconds_t>(timeout.InMicroseconds()) }; | 162 const TimeDelta this_timeout = finish_time - TimeTicks::Now(); |
172 const int select_result = | 163 const int timeout_ms = |
173 select(handle_ + 1, &read_fds, NULL, NULL, &timeout_struct); | 164 static_cast<int>(this_timeout.InMillisecondsRoundedUp()); |
| 165 if (timeout_ms <= 0) |
| 166 break; |
| 167 const int poll_result = poll(&pollfd, 1, timeout_ms); |
174 // Handle EINTR manually since we need to update the timeout value. | 168 // Handle EINTR manually since we need to update the timeout value. |
175 if (select_result == -1 && errno == EINTR) | 169 if (poll_result == -1 && errno == EINTR) |
176 continue; | 170 continue; |
177 if (select_result <= 0) | 171 // Return if other type of error or a timeout. |
| 172 if (poll_result <= 0) |
178 return bytes_read_total; | 173 return bytes_read_total; |
179 | 174 |
180 // select() only tells us that data is ready for reading, not how much. We | 175 // poll() only tells us that data is ready for reading, not how much. We |
181 // must Peek() for the amount ready for reading to avoid blocking. | 176 // must Peek() for the amount ready for reading to avoid blocking. |
182 DCHECK(FD_ISSET(handle_, &read_fds)); | 177 // At hang up (POLLHUP), the write end has been closed and there might still |
| 178 // be data to be read. |
| 179 // No special handling is needed for error (POLLERR); we can let any of the |
| 180 // following operations fail and handle it there. |
| 181 DCHECK(pollfd.revents & (POLLIN | POLLHUP | POLLERR)) << pollfd.revents; |
183 const size_t bytes_to_read = std::min(Peek(), length - bytes_read_total); | 182 const size_t bytes_to_read = std::min(Peek(), length - bytes_read_total); |
184 | 183 |
185 // There may be zero bytes to read if the socket at the other end closed. | 184 // There may be zero bytes to read if the socket at the other end closed. |
186 if (!bytes_to_read) | 185 if (!bytes_to_read) |
187 return bytes_read_total; | 186 return bytes_read_total; |
188 | 187 |
189 const size_t bytes_received = | 188 const size_t bytes_received = |
190 Receive(static_cast<char*>(buffer) + bytes_read_total, bytes_to_read); | 189 Receive(static_cast<char*>(buffer) + bytes_read_total, bytes_to_read); |
191 bytes_read_total += bytes_received; | 190 bytes_read_total += bytes_received; |
192 if (bytes_received != bytes_to_read) | 191 if (bytes_received != bytes_to_read) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 return len; | 244 return len; |
246 } | 245 } |
247 | 246 |
248 // static | 247 // static |
249 bool CancelableSyncSocket::CreatePair(CancelableSyncSocket* socket_a, | 248 bool CancelableSyncSocket::CreatePair(CancelableSyncSocket* socket_a, |
250 CancelableSyncSocket* socket_b) { | 249 CancelableSyncSocket* socket_b) { |
251 return SyncSocket::CreatePair(socket_a, socket_b); | 250 return SyncSocket::CreatePair(socket_a, socket_b); |
252 } | 251 } |
253 | 252 |
254 } // namespace base | 253 } // namespace base |
OLD | NEW |