| Index: net/socket/socket_posix.cc
|
| diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc
|
| index 09d9baec87e0139e41226b8a1b8b5a8de5c6a6c6..99f465df22d3aee093a9e1e8b6accf6df187162d 100644
|
| --- a/net/socket/socket_posix.cc
|
| +++ b/net/socket/socket_posix.cc
|
| @@ -250,10 +250,25 @@ 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
|
| DCHECK(!callback.is_null());
|
| DCHECK_LT(0, buf_len);
|
| @@ -269,9 +284,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;
|
| }
|
|
|
| @@ -372,10 +385,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()
|
| ReadCompleted();
|
| }
|
| }
|
| @@ -450,16 +463,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) {
|
|
|