Index: net/socket/socket_posix.cc |
diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc |
index 20cc92bf593a6d14ccf9cf6e94f5a0ae5f7411fe..b98be1c13fc13568bd11ef5742f3ea3dbcb1620c 100644 |
--- a/net/socket/socket_posix.cc |
+++ b/net/socket/socket_posix.cc |
@@ -253,10 +253,26 @@ bool SocketPosix::IsConnectedAndIdle() const { |
int SocketPosix::Read(IOBuffer* buf, |
int buf_len, |
const CompletionCallback& callback) { |
+ // Use base::Unretained() is safe here because OnFileCanReadWithoutBlocking() |
+ // won't be called if |this| is gone. |
+ int rv = |
+ ReadIfReady(buf, buf_len, |
+ base::Bind(&SocketPosix::RetryRead, base::Unretained(this))); |
+ if (rv == ERR_IO_PENDING) { |
+ read_buf_ = buf; |
+ read_buf_len_ = buf_len; |
+ read_callback_ = callback; |
+ } |
+ return rv; |
+} |
+ |
+int SocketPosix::ReadIfReady(IOBuffer* buf, |
+ int buf_len, |
+ const CompletionCallback& callback) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
DCHECK_NE(kInvalidSocket, socket_fd_); |
DCHECK(!waiting_connect_); |
- CHECK(read_callback_.is_null()); |
+ CHECK(read_if_ready_callback_.is_null()); |
// Synchronous operation not supported |
Bence
2017/03/03 16:33:41
What does this comment mean? Could it be removed?
xunjieli
2017/03/03 19:41:05
Done. Removed. I think having a callback as a requ
|
DCHECK(!callback.is_null()); |
DCHECK_LT(0, buf_len); |
@@ -272,9 +288,7 @@ int SocketPosix::Read(IOBuffer* buf, |
return MapSystemError(errno); |
} |
- read_buf_ = buf; |
- read_buf_len_ = buf_len; |
- read_callback_ = callback; |
+ read_if_ready_callback_ = callback; |
return ERR_IO_PENDING; |
} |
@@ -375,10 +389,10 @@ void SocketPosix::DetachFromThread() { |
void SocketPosix::OnFileCanReadWithoutBlocking(int fd) { |
TRACE_EVENT0(kNetTracingCategory, |
"SocketPosix::OnFileCanReadWithoutBlocking"); |
- DCHECK(!accept_callback_.is_null() || !read_callback_.is_null()); |
+ DCHECK(!accept_callback_.is_null() || !read_if_ready_callback_.is_null()); |
if (!accept_callback_.is_null()) { |
AcceptCompleted(); |
- } else { // !read_callback_.is_null() |
+ } else { // !read_if_ready_callback_.is_null() |
Bence
2017/03/03 16:33:41
Optional: remove this comment, remove DCHECK from
xunjieli
2017/03/03 19:41:05
Done.
|
ReadCompleted(); |
} |
} |
@@ -453,16 +467,29 @@ int SocketPosix::DoRead(IOBuffer* buf, int buf_len) { |
return rv >= 0 ? rv : MapSystemError(errno); |
} |
+void SocketPosix::RetryRead(int rv) { |
+ DCHECK(read_callback_); |
+ DCHECK(read_buf_); |
+ DCHECK_LT(0, read_buf_len_); |
+ |
+ if (rv == OK) { |
+ rv = ReadIfReady( |
+ read_buf_.get(), read_buf_len_, |
+ base::Bind(&SocketPosix::RetryRead, base::Unretained(this))); |
+ if (rv == ERR_IO_PENDING) |
+ return; |
+ } |
+ read_buf_ = nullptr; |
+ read_buf_len_ = 0; |
+ base::ResetAndReturn(&read_callback_).Run(rv); |
+} |
+ |
void SocketPosix::ReadCompleted() { |
- int rv = DoRead(read_buf_.get(), read_buf_len_); |
- if (rv == ERR_IO_PENDING) |
- return; |
+ DCHECK(read_if_ready_callback_); |
bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); |
DCHECK(ok); |
- read_buf_ = NULL; |
- read_buf_len_ = 0; |
- base::ResetAndReturn(&read_callback_).Run(rv); |
+ base::ResetAndReturn(&read_if_ready_callback_).Run(OK); |
} |
int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) { |