aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/transport
diff options
context:
space:
mode:
authorGravatar Craig Tiller <craig.tiller@gmail.com>2015-02-24 21:55:20 -0800
committerGravatar Craig Tiller <craig.tiller@gmail.com>2015-02-24 22:00:01 -0800
commitd1345ded70c390f4287072b2ec82a890bb980312 (patch)
tree80fe5bae3e02e238212d8a52c19deb59b76ac7d1 /src/core/transport
parentcb0a28eb86a22d4b220c8d025b96165cf68279f7 (diff)
Fix shutdown race in CHTTP2
After we have called closed() ensure that no other callbacks are ever made.
Diffstat (limited to 'src/core/transport')
-rw-r--r--src/core/transport/chttp2_transport.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index ccd8d0c376..f8b1db8d25 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -301,7 +301,7 @@ static void push_setting(transport *t, grpc_chttp2_setting_id id,
gpr_uint32 value);
static int prepare_callbacks(transport *t);
-static void run_callbacks(transport *t);
+static void run_callbacks(transport *t, const grpc_transport_callbacks *cb);
static int prepare_write(transport *t);
static void perform_write(transport *t, grpc_endpoint *ep);
@@ -706,6 +706,7 @@ static void unlock(transport *t) {
pending_goaway *goaways = NULL;
grpc_endpoint *ep = t->ep;
grpc_stream_op_buffer nuke_now;
+ const grpc_transport_callbacks *cb = t->cb;
grpc_sopb_init(&nuke_now);
if (t->nuke_later_sopb.nops) {
@@ -725,7 +726,7 @@ static void unlock(transport *t) {
}
/* gather any callbacks that need to be made */
- if (!t->calling_back && t->cb) {
+ if (!t->calling_back && cb) {
perform_callbacks = prepare_callbacks(t);
if (perform_callbacks) {
t->calling_back = 1;
@@ -733,6 +734,7 @@ static void unlock(transport *t) {
if (t->error_state == ERROR_STATE_SEEN) {
call_closed = 1;
t->calling_back = 1;
+ t->cb = NULL; /* no more callbacks */
t->error_state = ERROR_STATE_NOTIFIED;
}
if (t->num_pending_goaways) {
@@ -754,16 +756,16 @@ static void unlock(transport *t) {
/* perform some callbacks if necessary */
for (i = 0; i < num_goaways; i++) {
- t->cb->goaway(t->cb_user_data, &t->base, goaways[i].status,
- goaways[i].debug);
+ cb->goaway(t->cb_user_data, &t->base, goaways[i].status,
+ goaways[i].debug);
}
if (perform_callbacks) {
- run_callbacks(t);
+ run_callbacks(t, cb);
}
if (call_closed) {
- t->cb->closed(t->cb_user_data, &t->base);
+ cb->closed(t->cb_user_data, &t->base);
}
/* write some bytes if necessary */
@@ -1741,13 +1743,13 @@ static int prepare_callbacks(transport *t) {
return n;
}
-static void run_callbacks(transport *t) {
+static void run_callbacks(transport *t, const grpc_transport_callbacks *cb) {
stream *s;
while ((s = stream_list_remove_head(t, EXECUTING_CALLBACKS))) {
size_t nops = s->callback_sopb.nops;
s->callback_sopb.nops = 0;
- t->cb->recv_batch(t->cb_user_data, &t->base, (grpc_stream *)s,
- s->callback_sopb.ops, nops, s->callback_state);
+ cb->recv_batch(t->cb_user_data, &t->base, (grpc_stream *)s,
+ s->callback_sopb.ops, nops, s->callback_state);
}
}