aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/iomgr/tcp_windows.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/iomgr/tcp_windows.c')
-rw-r--r--src/core/iomgr/tcp_windows.c92
1 files changed, 27 insertions, 65 deletions
diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c
index c8483bd891..f16b4c1268 100644
--- a/src/core/iomgr/tcp_windows.c
+++ b/src/core/iomgr/tcp_windows.c
@@ -86,12 +86,10 @@ typedef struct grpc_tcp {
grpc_endpoint_read_cb read_cb;
void *read_user_data;
gpr_slice read_slice;
- int outstanding_read;
grpc_endpoint_write_cb write_cb;
void *write_user_data;
gpr_slice_buffer write_slices;
- int outstanding_write;
/* The IO Completion Port runs from another thread. We need some mechanism
to protect ourselves when requesting a shutdown. */
@@ -141,14 +139,13 @@ static void on_read(void *tcpp, int from_iocp) {
return;
}
- GPR_ASSERT(tcp->outstanding_read);
+ GPR_ASSERT(tcp->socket->read_info.outstanding);
if (socket->read_info.wsa_error != 0) {
char *utf8_message = gpr_format_message(info->wsa_error);
gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message);
gpr_free(utf8_message);
status = GRPC_ENDPOINT_CB_ERROR;
- socket->closed_early = 1;
} else {
if (info->bytes_transfered != 0) {
sub = gpr_slice_sub(tcp->read_slice, 0, info->bytes_transfered);
@@ -161,7 +158,7 @@ static void on_read(void *tcpp, int from_iocp) {
}
}
- tcp->outstanding_read = 0;
+ tcp->socket->read_info.outstanding = 0;
tcp_unref(tcp);
cb(opaque, slice, nslices, status);
@@ -175,13 +172,15 @@ static void win_notify_on_read(grpc_endpoint *ep,
int status;
DWORD bytes_read = 0;
DWORD flags = 0;
- int error;
WSABUF buffer;
- GPR_ASSERT(!tcp->outstanding_read);
- GPR_ASSERT(!tcp->shutting_down);
+ GPR_ASSERT(!tcp->socket->read_info.outstanding);
+ if (tcp->shutting_down) {
+ cb(arg, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN);
+ return;
+ }
tcp_ref(tcp);
- tcp->outstanding_read = 1;
+ tcp->socket->read_info.outstanding = 1;
tcp->read_cb = cb;
tcp->read_user_data = arg;
@@ -208,34 +207,13 @@ static void win_notify_on_read(grpc_endpoint *ep,
status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags,
&info->overlapped, NULL);
- if (status == 0) {
- grpc_socket_notify_on_read(tcp->socket, on_read, tcp);
- return;
- }
-
- error = WSAGetLastError();
-
- if (error != WSA_IO_PENDING) {
- char *utf8_message = gpr_format_message(WSAGetLastError());
- gpr_log(GPR_ERROR, "WSARecv error: %s - this means we're going to leak.",
- utf8_message);
- gpr_free(utf8_message);
- /* I'm pretty sure this is a very bad situation there. Hence the log.
- What will happen now is that the socket will neither wait for read
- or write, unless the caller retry, which is unlikely, but I am not
- sure if that's guaranteed. And there might also be a write pending.
- This means that the future orphanage of that socket will be in limbo,
- and we're going to leak it. I have no idea what could cause this
- specific case however, aside from a parameter error from our call.
- Normal read errors would actually happen during the overlapped
- operation, which is the supported way to go for that. */
- tcp->outstanding_read = 0;
- tcp_unref(tcp);
- cb(arg, NULL, 0, GRPC_ENDPOINT_CB_ERROR);
- /* Per the comment above, I'm going to treat that case as a hard failure
- for now, and leave the option to catch that and debug. */
- __debugbreak();
- return;
+ if (status != 0) {
+ int wsa_error = WSAGetLastError();
+ if (wsa_error != WSA_IO_PENDING) {
+ info->wsa_error = wsa_error;
+ on_read(tcp, 1);
+ return;
+ }
}
grpc_socket_notify_on_read(tcp->socket, on_read, tcp);
@@ -260,7 +238,7 @@ static void on_write(void *tcpp, int from_iocp) {
}
gpr_mu_unlock(&tcp->mu);
- GPR_ASSERT(tcp->outstanding_write);
+ GPR_ASSERT(tcp->socket->write_info.outstanding);
if (do_abort) {
if (from_iocp) gpr_slice_buffer_reset_and_unref(&tcp->write_slices);
@@ -274,13 +252,12 @@ static void on_write(void *tcpp, int from_iocp) {
gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message);
gpr_free(utf8_message);
status = GRPC_ENDPOINT_CB_ERROR;
- tcp->socket->closed_early = 1;
} else {
GPR_ASSERT(info->bytes_transfered == tcp->write_slices.length);
}
gpr_slice_buffer_reset_and_unref(&tcp->write_slices);
- tcp->outstanding_write = 0;
+ tcp->socket->write_info.outstanding = 0;
tcp_unref(tcp);
cb(opaque, status);
@@ -301,11 +278,13 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep,
WSABUF *allocated = NULL;
WSABUF *buffers = local_buffers;
- GPR_ASSERT(!tcp->outstanding_write);
- GPR_ASSERT(!tcp->shutting_down);
+ GPR_ASSERT(!tcp->socket->write_info.outstanding);
+ if (tcp->shutting_down) {
+ return GRPC_ENDPOINT_WRITE_ERROR;
+ }
tcp_ref(tcp);
- tcp->outstanding_write = 1;
+ tcp->socket->write_info.outstanding = 1;
tcp->write_cb = cb;
tcp->write_user_data = arg;
@@ -341,7 +320,7 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep,
}
if (allocated) gpr_free(allocated);
gpr_slice_buffer_reset_and_unref(&tcp->write_slices);
- tcp->outstanding_write = 0;
+ tcp->socket->write_info.outstanding = 0;
tcp_unref(tcp);
return ret;
}
@@ -353,29 +332,12 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep,
&bytes_sent, 0, &socket->write_info.overlapped, NULL);
if (allocated) gpr_free(allocated);
- /* It is possible the operation completed then. But we'd still get an IOCP
- notification. So let's ignore it and wait for the IOCP. */
if (status != 0) {
- int error = WSAGetLastError();
- if (error != WSA_IO_PENDING) {
- char *utf8_message = gpr_format_message(WSAGetLastError());
- gpr_log(GPR_ERROR, "WSASend error: %s - this means we're going to leak.",
- utf8_message);
- gpr_free(utf8_message);
- /* I'm pretty sure this is a very bad situation there. Hence the log.
- What will happen now is that the socket will neither wait for read
- or write, unless the caller retry, which is unlikely, but I am not
- sure if that's guaranteed. And there might also be a read pending.
- This means that the future orphanage of that socket will be in limbo,
- and we're going to leak it. I have no idea what could cause this
- specific case however, aside from a parameter error from our call.
- Normal read errors would actually happen during the overlapped
- operation, which is the supported way to go for that. */
- tcp->outstanding_write = 0;
+ int wsa_error = WSAGetLastError();
+ if (wsa_error != WSA_IO_PENDING) {
+ gpr_slice_buffer_reset_and_unref(&tcp->write_slices);
+ tcp->socket->write_info.outstanding = 0;
tcp_unref(tcp);
- /* Per the comment above, I'm going to treat that case as a hard failure
- for now, and leave the option to catch that and debug. */
- __debugbreak();
return GRPC_ENDPOINT_WRITE_ERROR;
}
}