From ae2b02a537ddee3fd127587fc6f693dabfa4693c Mon Sep 17 00:00:00 2001
From: yang-g <yangg@google.com>
Date: Tue, 3 Dec 2019 11:00:14 -0800
Subject: [PATCH] Support client side handshaker handoff fd

---
 .../chttp2/client/chttp2_connector.cc         | 27 ++++++++++++-------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.cc b/src/core/ext/transport/chttp2/client/chttp2_connector.cc
index 431748be46f..b5593cb17db 100644
--- a/src/core/ext/transport/chttp2/client/chttp2_connector.cc
+++ b/src/core/ext/transport/chttp2/client/chttp2_connector.cc
@@ -139,20 +139,22 @@ void Chttp2Connector::OnHandshakeDone(void* arg, grpc_error* error) {
         error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("connector shutdown");
         // We were shut down after handshaking completed successfully, so
         // destroy the endpoint here.
-        // TODO(ctiller): It is currently necessary to shutdown endpoints
-        // before destroying them, even if we know that there are no
-        // pending read/write callbacks.  This should be fixed, at which
-        // point this can be removed.
-        grpc_endpoint_shutdown(args->endpoint, GRPC_ERROR_REF(error));
-        grpc_endpoint_destroy(args->endpoint);
-        grpc_channel_args_destroy(args->args);
-        grpc_slice_buffer_destroy_internal(args->read_buffer);
-        gpr_free(args->read_buffer);
+        if (args->endpoint != nullptr) {
+          // TODO(ctiller): It is currently necessary to shutdown endpoints
+          // before destroying them, even if we know that there are no
+          // pending read/write callbacks.  This should be fixed, at which
+          // point this can be removed.
+          grpc_endpoint_shutdown(args->endpoint, GRPC_ERROR_REF(error));
+          grpc_endpoint_destroy(args->endpoint);
+          grpc_channel_args_destroy(args->args);
+          grpc_slice_buffer_destroy_internal(args->read_buffer);
+          gpr_free(args->read_buffer);
+        }
       } else {
         error = GRPC_ERROR_REF(error);
       }
       self->result_->Reset();
-    } else {
+    } else if (args->endpoint != nullptr) {
       grpc_endpoint_delete_from_pollset_set(args->endpoint,
                                             self->args_.interested_parties);
       self->result_->transport =
@@ -187,6 +189,11 @@ void Chttp2Connector::OnHandshakeDone(void* arg, grpc_error* error) {
       grpc_chttp2_transport_start_reading(self->result_->transport,
                                           args->read_buffer, nullptr);
       self->result_->channel_args = args->args;
+    } else {
+      // If the handshaking succeeded but there is no endpoint, then the
+      // handshaker may have handed off the connection to some external
+      // code. Just verify that exit_early flag is set.
+      GPR_DEBUG_ASSERT(args->exit_early);
     }
     grpc_closure* notify = self->notify_;
     self->notify_ = nullptr;