|
|
|
@ -116,6 +116,7 @@ typedef struct grpc_tcp { |
|
|
|
|
to protect ourselves when requesting a shutdown. */ |
|
|
|
|
gpr_mu mu; |
|
|
|
|
int shutting_down; |
|
|
|
|
grpc_error *shutdown_error; |
|
|
|
|
|
|
|
|
|
char *peer_string; |
|
|
|
|
} grpc_tcp; |
|
|
|
@ -125,6 +126,7 @@ static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { |
|
|
|
|
gpr_mu_destroy(&tcp->mu); |
|
|
|
|
gpr_free(tcp->peer_string); |
|
|
|
|
grpc_resource_user_unref(exec_ctx, tcp->resource_user); |
|
|
|
|
if (tcp->shutting_down) GRPC_ERROR_UNREF(tcp->shutdown_error); |
|
|
|
|
gpr_free(tcp); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -182,7 +184,7 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, grpc_error *error) { |
|
|
|
|
grpc_slice_buffer_add(tcp->read_slices, sub); |
|
|
|
|
} else { |
|
|
|
|
grpc_slice_unref_internal(exec_ctx, tcp->read_slice); |
|
|
|
|
error = GRPC_ERROR_CREATE("End of TCP stream"); |
|
|
|
|
error = tcp->shutting_down ? GRPC_ERROR_CREATE_REFERENCING("TCP stream shutting down", &tcp->shutdown_error, 1) : GRPC_ERROR_CREATE("End of TCP stream"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -204,7 +206,7 @@ static void win_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, |
|
|
|
|
|
|
|
|
|
if (tcp->shutting_down) { |
|
|
|
|
grpc_closure_sched(exec_ctx, cb, |
|
|
|
|
GRPC_ERROR_CREATE("TCP socket is shutting down")); |
|
|
|
|
GRPC_ERROR_CREATE_REFERENCING("TCP socket is shutting down", &tcp->shutdown_error, 1)); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -292,7 +294,7 @@ static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, |
|
|
|
|
|
|
|
|
|
if (tcp->shutting_down) { |
|
|
|
|
grpc_closure_sched(exec_ctx, cb, |
|
|
|
|
GRPC_ERROR_CREATE("TCP socket is shutting down")); |
|
|
|
|
GRPC_ERROR_CREATE_REFERENCING("TCP socket is shutting down", &tcp->shutdown_error, 1)); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -373,12 +375,18 @@ static void win_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, |
|
|
|
|
we're not going to protect against these. However the IO Completion Port |
|
|
|
|
callback will happen from another thread, so we need to protect against |
|
|
|
|
concurrent access of the data structure in that regard. */ |
|
|
|
|
static void win_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { |
|
|
|
|
static void win_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why) { |
|
|
|
|
grpc_tcp *tcp = (grpc_tcp *)ep; |
|
|
|
|
gpr_mu_lock(&tcp->mu); |
|
|
|
|
/* At that point, what may happen is that we're already inside the IOCP
|
|
|
|
|
callback. See the comments in on_read and on_write. */ |
|
|
|
|
tcp->shutting_down = 1; |
|
|
|
|
if (!tcp->shutting_down) { |
|
|
|
|
tcp->shutting_down = 1; |
|
|
|
|
tcp->shutdown_error = why; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
GRPC_ERROR_UNREF(why); |
|
|
|
|
} |
|
|
|
|
grpc_winsocket_shutdown(tcp->socket); |
|
|
|
|
gpr_mu_unlock(&tcp->mu); |
|
|
|
|
grpc_resource_user_shutdown(exec_ctx, tcp->resource_user); |
|
|
|
|