| Index: net/socket/socket_posix.cc
|
| diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc
|
| index 20cc92bf593a6d14ccf9cf6e94f5a0ae5f7411fe..6955aa2a1e83a565c12f2700db5e2d1a618effce 100644
|
| --- a/net/socket/socket_posix.cc
|
| +++ b/net/socket/socket_posix.cc
|
| @@ -253,11 +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());
|
| - // Synchronous operation not supported
|
| + CHECK(read_if_ready_callback_.is_null());
|
| DCHECK(!callback.is_null());
|
| DCHECK_LT(0, buf_len);
|
|
|
| @@ -272,9 +287,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 +388,10 @@ void SocketPosix::DetachFromThread() {
|
| void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
|
| TRACE_EVENT0(kNetTracingCategory,
|
| "SocketPosix::OnFileCanReadWithoutBlocking");
|
| - DCHECK(!accept_callback_.is_null() || !read_callback_.is_null());
|
| if (!accept_callback_.is_null()) {
|
| AcceptCompleted();
|
| - } else { // !read_callback_.is_null()
|
| + } else {
|
| + DCHECK(!read_if_ready_callback_.is_null());
|
| ReadCompleted();
|
| }
|
| }
|
| @@ -453,16 +466,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) {
|
| @@ -509,6 +535,8 @@ void SocketPosix::StopWatchingAndCleanUp() {
|
| read_callback_.Reset();
|
| }
|
|
|
| + read_if_ready_callback_.Reset();
|
| +
|
| if (!write_callback_.is_null()) {
|
| write_buf_ = NULL;
|
| write_buf_len_ = 0;
|
|
|