diff options
-rw-r--r-- | src/core/transport/chttp2_transport.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 386ba04b9c..aa6a860c67 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -345,19 +345,38 @@ static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) { gpr_ref(&t->shutdown_ep_refs); } -static void allow_endpoint_shutdown(grpc_chttp2_transport *t) { +static void allow_endpoint_shutdown_locked(grpc_chttp2_transport *t) { if (gpr_unref(&t->shutdown_ep_refs)) { - grpc_endpoint_shutdown(t->ep); + if (t->ep) { + grpc_endpoint_shutdown(t->ep); + } + } +} + +static void allow_endpoint_shutdown_unlocked(grpc_chttp2_transport *t) { + if (gpr_unref(&t->shutdown_ep_refs)) { + gpr_mu_lock(&t->mu); + if (t->ep) { + grpc_endpoint_shutdown(t->ep); + } + gpr_mu_unlock(&t->mu); } } +static void destroy_endpoint(grpc_chttp2_transport *t) { + grpc_endpoint_destroy(t->ep); + t->ep = NULL; + UNREF_TRANSPORT( + t, "disconnect"); /* safe because we'll still have the ref for write */ +} + static void close_transport_locked(grpc_chttp2_transport *t) { if (!t->closed) { t->closed = 1; connectivity_state_set(&t->global, GRPC_CHANNEL_FATAL_FAILURE, "close_transport"); if (t->ep) { - allow_endpoint_shutdown(t); + allow_endpoint_shutdown_locked(t); } } } @@ -525,10 +544,10 @@ void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success) { grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr; grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); - allow_endpoint_shutdown(t); - lock(t); + allow_endpoint_shutdown_locked(t); + if (!success) { drop_connection(t); } @@ -540,10 +559,7 @@ void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success) { from starting */ t->writing_active = 0; if (t->ep && !t->endpoint_reading) { - grpc_endpoint_destroy(t->ep); - t->ep = NULL; - UNREF_TRANSPORT( - t, "disconnect"); /* safe because we'll still have the ref for write */ + destroy_endpoint(t); } unlock(t); @@ -1073,10 +1089,7 @@ static void update_global_window(void *args, gpr_uint32 id, void *stream) { static void read_error_locked(grpc_chttp2_transport *t) { t->endpoint_reading = 0; if (!t->writing_active && t->ep) { - grpc_endpoint_destroy(t->ep); - t->ep = NULL; - /* safe as we still have a ref for read */ - UNREF_TRANSPORT(t, "disconnect"); + destroy_endpoint(t); } } @@ -1122,6 +1135,7 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { read_error_locked(t); } else if (!t->closed) { keep_reading = 1; + REF_TRANSPORT(t, "keep_reading"); prevent_endpoint_shutdown(t); } gpr_slice_buffer_reset_and_unref(&t->read_buffer); @@ -1142,7 +1156,8 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { ret = 0; break; } - allow_endpoint_shutdown(t); + allow_endpoint_shutdown_unlocked(t); + UNREF_TRANSPORT(t, "keep_reading"); return ret; } else { UNREF_TRANSPORT(t, "recv_data"); |