Index: net/socket/tcp_client_socket_win.cc |
=================================================================== |
--- net/socket/tcp_client_socket_win.cc (revision 187920) |
+++ net/socket/tcp_client_socket_win.cc (working copy) |
@@ -957,7 +957,6 @@ |
DWORD num_bytes, flags; |
BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_, |
&num_bytes, FALSE, &flags); |
- WSAResetEvent(core_->read_overlapped_.hEvent); |
waiting_read_ = false; |
int rv; |
if (ok) { |
@@ -975,6 +974,7 @@ |
net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, |
CreateNetLogSocketErrorCallback(rv, os_error)); |
} |
+ WSAResetEvent(core_->read_overlapped_.hEvent); |
core_->read_iobuffer_ = NULL; |
core_->read_buffer_length_ = 0; |
DoReadCallback(rv); |
@@ -1025,22 +1025,29 @@ |
if (rv == SOCKET_ERROR) { |
os_error = WSAGetLastError(); |
rv = MapSystemError(os_error); |
- } else if (network_events.lNetworkEvents & FD_READ) { |
+ } else if (network_events.lNetworkEvents) { |
+ DCHECK_EQ(network_events.lNetworkEvents & ~(FD_READ | FD_CLOSE), 0); |
+ // If network_events.lNetworkEvents is FD_CLOSE and |
+ // network_events.iErrorCode[FD_CLOSE_BIT] is 0, it is a graceful |
+ // connection closure. It is tempting to directly set rv to 0 in |
+ // this case, but the MSDN pages for WSAEventSelect and |
+ // WSAAsyncSelect recommend we still call DoRead(): |
+ // FD_CLOSE should only be posted after all data is read from a |
+ // socket, but an application should check for remaining data upon |
+ // receipt of FD_CLOSE to avoid any possibility of losing data. |
+ // |
+ // If network_events.iErrorCode[FD_READ_BIT] or |
+ // network_events.iErrorCode[FD_CLOSE_BIT] is nonzero, still call |
+ // DoRead() because recv() reports a more accurate error code |
+ // (WSAECONNRESET vs. WSAECONNABORTED) when the connection was |
+ // reset. |
rv = DoRead(core_->read_iobuffer_, core_->read_buffer_length_, |
read_callback_); |
if (rv == ERR_IO_PENDING) |
return; |
- } else if (network_events.lNetworkEvents & FD_CLOSE) { |
- if (network_events.iErrorCode[FD_CLOSE_BIT]) { |
- rv = MapSystemError(network_events.iErrorCode[FD_CLOSE_BIT]); |
- net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, |
- CreateNetLogSocketErrorCallback(rv, os_error)); |
- } else { |
- rv = 0; |
- } |
} else { |
- // This should not happen but I have seen cases where we will get |
- // signaled but the network events flags are all clear (0). |
+ // This may happen because Read() may succeed synchronously and |
+ // consume all the received data without resetting the event object. |
core_->WatchForRead(); |
return; |
} |