aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/transport/chttp2_transport.c43
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");