Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3077)

Unified Diff: base/sync_socket_posix.cc

Issue 23875019: Add SyncSocket::ReceiveWithTimeout() and SyncSocket unit tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixes. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/sync_socket_posix.cc
diff --git a/base/sync_socket_posix.cc b/base/sync_socket_posix.cc
index 257916df3357a21962a4f6b9fe7561a09c286d50..d76b00833c10b7d6332952b3ae196ea89ff175ba 100644
--- a/base/sync_socket_posix.cc
+++ b/base/sync_socket_posix.cc
@@ -19,7 +19,6 @@
#include "base/file_util.h"
#include "base/logging.h"
-
namespace base {
namespace {
@@ -93,6 +92,7 @@ bool SyncSocket::Close() {
}
size_t SyncSocket::Send(const void* buffer, size_t length) {
+ DCHECK_GT(length, 0u);
DCHECK_LE(length, kMaxMessageLength);
const char* charbuffer = static_cast<const char*>(buffer);
int len = file_util::WriteFileDescriptor(handle_, charbuffer, length);
@@ -101,6 +101,7 @@ size_t SyncSocket::Send(const void* buffer, size_t length) {
}
size_t SyncSocket::Receive(void* buffer, size_t length) {
+ DCHECK_GT(length, 0u);
DCHECK_LE(length, kMaxMessageLength);
char* charbuffer = static_cast<char*>(buffer);
if (file_util::ReadFromFD(handle_, charbuffer, length))
@@ -108,13 +109,56 @@ size_t SyncSocket::Receive(void* buffer, size_t length) {
return 0;
}
+size_t SyncSocket::ReceiveWithTimeout(void* buffer,
+ size_t length,
+ TimeDelta timeout) {
willchan no longer on Chromium 2013/10/04 21:01:35 Please use ThreadRestrictions::AssertIOAllowed();
DaleCurtis 2013/10/04 21:08:39 I'll check if that can be done.
DaleCurtis 2013/10/04 23:11:32 Done.
+ DCHECK_GT(length, 0u);
+ DCHECK_LE(length, kMaxMessageLength);
+
+ // Only timeouts greater than zero and less than one second are allowed.
+ DCHECK_GT(timeout.InMicroseconds(), 0);
+ DCHECK(timeout.InMicroseconds() < Time::kMicrosecondsPerSecond);
+
+ // Track the start time so we can reduce the timeout as data is read.
+ TimeTicks start_time = base::TimeTicks::Now();
willchan no longer on Chromium 2013/10/04 21:01:35 drop the base::
DaleCurtis 2013/10/04 23:11:32 Done.
+
+ fd_set rfds;
willchan no longer on Chromium 2013/10/04 21:01:35 Please choose a more descriptive name.
DaleCurtis 2013/10/04 23:11:32 Done.
+ size_t bytes_read_total = 0;
+ char* charbuffer = static_cast<char*>(buffer);
+ do {
+ FD_ZERO(&rfds);
+ FD_SET(handle_, &rfds);
Nico 2013/10/04 05:35:12 You need to check that handle_ is < FD_SETSIZE, el
DaleCurtis 2013/10/04 23:11:32 Done.
+
+ // Wait for data to become available.
+ struct timeval timeout_struct = { 0, timeout.InMicroseconds() };
+ const int select_result = HANDLE_EINTR(
willchan no longer on Chromium 2013/10/04 21:01:35 I think there's a bug here, right? HANDLE_EINTR()
DaleCurtis 2013/10/04 21:08:39 select() will update the timeout struct on EINTR:
willchan no longer on Chromium 2013/10/09 20:06:52 How about the non-linux posix platforms? What happ
DaleCurtis 2013/10/09 21:55:40 Man page is sadly conflicting, saying both that it
+ select(handle_ + 1, &rfds, NULL, NULL, &timeout_struct));
+ if (select_result <= 0)
+ return bytes_read_total;
+
+ // select() only tells us that data is ready for reading, not how much. We
+ // must Peek() for the amount ready for reading to avoid blocking.
willchan no longer on Chromium 2013/10/04 21:01:35 Why don't you just use read() instead and do the l
DaleCurtis 2013/10/04 21:08:39 Code reuse? What's the benefit of reimplementing t
willchan no longer on Chromium 2013/10/09 20:06:52 Sorry, I was hung up on disliking the API that alw
+ DCHECK(FD_ISSET(handle_, &rfds));
+ const size_t bytes_to_read = std::min(Peek(), length - bytes_read_total);
+ const size_t bytes_received =
+ Receive(charbuffer + bytes_read_total, bytes_to_read);
+ bytes_read_total += bytes_received;
+ if (bytes_received != bytes_to_read)
+ return bytes_read_total;
+ } while (bytes_read_total < length &&
+ (timeout -= (base::TimeTicks::Now() - start_time)) >
willchan no longer on Chromium 2013/10/04 21:01:35 drop the base::
DaleCurtis 2013/10/04 23:11:32 Done.
+ base::TimeDelta());
+ return bytes_read_total;
+}
+
size_t SyncSocket::Peek() {
int number_chars;
if (-1 == ioctl(handle_, FIONREAD, &number_chars)) {
// If there is an error in ioctl, signal that the channel would block.
return 0;
}
- return (size_t) number_chars;
+ DCHECK_GE(number_chars, 0);
+ return number_chars;
}
CancelableSyncSocket::CancelableSyncSocket() {}

Powered by Google App Engine
This is Rietveld 408576698