Browse Source

Fix shutdown race in CHTTP2

After we have called closed() ensure that no other callbacks are ever made.
Craig Tiller 10 năm trước cách đây
mục cha
commit
d1345ded70
1 tập tin đã thay đổi với 11 bổ sung9 xóa
  1. 11 9
      src/core/transport/chttp2_transport.c

+ 11 - 9
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);
   }
 }