|  | @@ -66,10 +66,12 @@ class SecurityHandshaker : public Handshaker {
 | 
	
		
			
				|  |  |    void HandshakeFailedLocked(grpc_error* error);
 | 
	
		
			
				|  |  |    void CleanupArgsForFailureLocked();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  static void ScheduleRead(void* arg, grpc_error* /* error */);
 | 
	
		
			
				|  |  | -  static void ScheduleWrite(void* arg, grpc_error* /* error */);
 | 
	
		
			
				|  |  |    static void OnHandshakeDataReceivedFromPeerFn(void* arg, grpc_error* error);
 | 
	
		
			
				|  |  |    static void OnHandshakeDataSentToPeerFn(void* arg, grpc_error* error);
 | 
	
		
			
				|  |  | +  static void OnHandshakeDataReceivedFromPeerFnScheduler(void* arg,
 | 
	
		
			
				|  |  | +                                                         grpc_error* error);
 | 
	
		
			
				|  |  | +  static void OnHandshakeDataSentToPeerFnScheduler(void* arg,
 | 
	
		
			
				|  |  | +                                                   grpc_error* error);
 | 
	
		
			
				|  |  |    static void OnHandshakeNextDoneGrpcWrapper(
 | 
	
		
			
				|  |  |        tsi_result result, void* user_data, const unsigned char* bytes_to_send,
 | 
	
		
			
				|  |  |        size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result);
 | 
	
	
		
			
				|  | @@ -96,8 +98,6 @@ class SecurityHandshaker : public Handshaker {
 | 
	
		
			
				|  |  |    size_t handshake_buffer_size_;
 | 
	
		
			
				|  |  |    unsigned char* handshake_buffer_;
 | 
	
		
			
				|  |  |    grpc_slice_buffer outgoing_;
 | 
	
		
			
				|  |  | -  grpc_closure schedule_read_closure_;
 | 
	
		
			
				|  |  | -  grpc_closure schedule_write_closure_;
 | 
	
		
			
				|  |  |    grpc_closure on_handshake_data_sent_to_peer_;
 | 
	
		
			
				|  |  |    grpc_closure on_handshake_data_received_from_peer_;
 | 
	
		
			
				|  |  |    grpc_closure on_peer_checked_;
 | 
	
	
		
			
				|  | @@ -122,17 +122,6 @@ SecurityHandshaker::SecurityHandshaker(tsi_handshaker* handshaker,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    gpr_mu_init(&mu_);
 | 
	
		
			
				|  |  |    grpc_slice_buffer_init(&outgoing_);
 | 
	
		
			
				|  |  | -  GRPC_CLOSURE_INIT(&schedule_read_closure_, &SecurityHandshaker::ScheduleRead,
 | 
	
		
			
				|  |  | -                    this, grpc_schedule_on_exec_ctx);
 | 
	
		
			
				|  |  | -  GRPC_CLOSURE_INIT(&schedule_write_closure_,
 | 
	
		
			
				|  |  | -                    &SecurityHandshaker::ScheduleWrite, this,
 | 
	
		
			
				|  |  | -                    grpc_schedule_on_exec_ctx);
 | 
	
		
			
				|  |  | -  GRPC_CLOSURE_INIT(&on_handshake_data_sent_to_peer_,
 | 
	
		
			
				|  |  | -                    &SecurityHandshaker::OnHandshakeDataSentToPeerFn, this,
 | 
	
		
			
				|  |  | -                    grpc_schedule_on_exec_ctx);
 | 
	
		
			
				|  |  | -  GRPC_CLOSURE_INIT(&on_handshake_data_received_from_peer_,
 | 
	
		
			
				|  |  | -                    &SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn,
 | 
	
		
			
				|  |  | -                    this, grpc_schedule_on_exec_ctx);
 | 
	
		
			
				|  |  |    GRPC_CLOSURE_INIT(&on_peer_checked_, &SecurityHandshaker::OnPeerCheckedFn,
 | 
	
		
			
				|  |  |                      this, grpc_schedule_on_exec_ctx);
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -293,19 +282,6 @@ grpc_error* SecurityHandshaker::CheckPeerLocked() {
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void SecurityHandshaker::ScheduleRead(void* arg, grpc_error* /* error */) {
 | 
	
		
			
				|  |  | -  SecurityHandshaker* h = static_cast<SecurityHandshaker*>(arg);
 | 
	
		
			
				|  |  | -  grpc_endpoint_read(h->args_->endpoint, h->args_->read_buffer,
 | 
	
		
			
				|  |  | -                     &h->on_handshake_data_received_from_peer_,
 | 
	
		
			
				|  |  | -                     /*urgent=*/true);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -void SecurityHandshaker::ScheduleWrite(void* arg, grpc_error* /* error */) {
 | 
	
		
			
				|  |  | -  SecurityHandshaker* h = static_cast<SecurityHandshaker*>(arg);
 | 
	
		
			
				|  |  | -  grpc_endpoint_write(h->args_->endpoint, &h->outgoing_,
 | 
	
		
			
				|  |  | -                      &h->on_handshake_data_sent_to_peer_, nullptr);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  grpc_error* SecurityHandshaker::OnHandshakeNextDoneLocked(
 | 
	
		
			
				|  |  |      tsi_result result, const unsigned char* bytes_to_send,
 | 
	
		
			
				|  |  |      size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result) {
 | 
	
	
		
			
				|  | @@ -317,7 +293,13 @@ grpc_error* SecurityHandshaker::OnHandshakeNextDoneLocked(
 | 
	
		
			
				|  |  |    // Read more if we need to.
 | 
	
		
			
				|  |  |    if (result == TSI_INCOMPLETE_DATA) {
 | 
	
		
			
				|  |  |      GPR_ASSERT(bytes_to_send_size == 0);
 | 
	
		
			
				|  |  | -    ExecCtx::Run(DEBUG_LOCATION, &schedule_read_closure_, GRPC_ERROR_NONE);
 | 
	
		
			
				|  |  | +    grpc_endpoint_read(
 | 
	
		
			
				|  |  | +        args_->endpoint, args_->read_buffer,
 | 
	
		
			
				|  |  | +        GRPC_CLOSURE_INIT(
 | 
	
		
			
				|  |  | +            &on_handshake_data_received_from_peer_,
 | 
	
		
			
				|  |  | +            &SecurityHandshaker::OnHandshakeDataReceivedFromPeerFnScheduler,
 | 
	
		
			
				|  |  | +            this, grpc_schedule_on_exec_ctx),
 | 
	
		
			
				|  |  | +        /*urgent=*/true);
 | 
	
		
			
				|  |  |      return error;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    if (result != TSI_OK) {
 | 
	
	
		
			
				|  | @@ -335,10 +317,22 @@ grpc_error* SecurityHandshaker::OnHandshakeNextDoneLocked(
 | 
	
		
			
				|  |  |          reinterpret_cast<const char*>(bytes_to_send), bytes_to_send_size);
 | 
	
		
			
				|  |  |      grpc_slice_buffer_reset_and_unref_internal(&outgoing_);
 | 
	
		
			
				|  |  |      grpc_slice_buffer_add(&outgoing_, to_send);
 | 
	
		
			
				|  |  | -    ExecCtx::Run(DEBUG_LOCATION, &schedule_write_closure_, GRPC_ERROR_NONE);
 | 
	
		
			
				|  |  | +    grpc_endpoint_write(
 | 
	
		
			
				|  |  | +        args_->endpoint, &outgoing_,
 | 
	
		
			
				|  |  | +        GRPC_CLOSURE_INIT(
 | 
	
		
			
				|  |  | +            &on_handshake_data_sent_to_peer_,
 | 
	
		
			
				|  |  | +            &SecurityHandshaker::OnHandshakeDataSentToPeerFnScheduler, this,
 | 
	
		
			
				|  |  | +            grpc_schedule_on_exec_ctx),
 | 
	
		
			
				|  |  | +        nullptr);
 | 
	
		
			
				|  |  |    } else if (handshaker_result == nullptr) {
 | 
	
		
			
				|  |  |      // There is nothing to send, but need to read from peer.
 | 
	
		
			
				|  |  | -    ExecCtx::Run(DEBUG_LOCATION, &schedule_read_closure_, GRPC_ERROR_NONE);
 | 
	
		
			
				|  |  | +    grpc_endpoint_read(
 | 
	
		
			
				|  |  | +        args_->endpoint, args_->read_buffer,
 | 
	
		
			
				|  |  | +        GRPC_CLOSURE_INIT(
 | 
	
		
			
				|  |  | +            &on_handshake_data_received_from_peer_,
 | 
	
		
			
				|  |  | +            &SecurityHandshaker::OnHandshakeDataReceivedFromPeerFnScheduler,
 | 
	
		
			
				|  |  | +            this, grpc_schedule_on_exec_ctx),
 | 
	
		
			
				|  |  | +        /*urgent=*/true);
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  |      // Handshake has finished, check peer and so on.
 | 
	
		
			
				|  |  |      error = CheckPeerLocked();
 | 
	
	
		
			
				|  | @@ -381,6 +375,19 @@ grpc_error* SecurityHandshaker::DoHandshakerNextLocked(
 | 
	
		
			
				|  |  |                                     hs_result);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// This callback might be run inline while we are still holding on to the mutex,
 | 
	
		
			
				|  |  | +// so schedule OnHandshakeDataReceivedFromPeerFn on ExecCtx to avoid a deadlock.
 | 
	
		
			
				|  |  | +void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFnScheduler(
 | 
	
		
			
				|  |  | +    void* arg, grpc_error* error) {
 | 
	
		
			
				|  |  | +  SecurityHandshaker* h = static_cast<SecurityHandshaker*>(arg);
 | 
	
		
			
				|  |  | +  grpc_core::ExecCtx::Run(
 | 
	
		
			
				|  |  | +      DEBUG_LOCATION,
 | 
	
		
			
				|  |  | +      GRPC_CLOSURE_INIT(&h->on_handshake_data_received_from_peer_,
 | 
	
		
			
				|  |  | +                        &SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn,
 | 
	
		
			
				|  |  | +                        h, grpc_schedule_on_exec_ctx),
 | 
	
		
			
				|  |  | +      GRPC_ERROR_REF(error));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn(void* arg,
 | 
	
		
			
				|  |  |                                                             grpc_error* error) {
 | 
	
		
			
				|  |  |    RefCountedPtr<SecurityHandshaker> h(static_cast<SecurityHandshaker*>(arg));
 | 
	
	
		
			
				|  | @@ -402,6 +409,19 @@ void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn(void* arg,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// This callback might be run inline while we are still holding on to the mutex,
 | 
	
		
			
				|  |  | +// so schedule OnHandshakeDataSentToPeerFn on ExecCtx to avoid a deadlock.
 | 
	
		
			
				|  |  | +void SecurityHandshaker::OnHandshakeDataSentToPeerFnScheduler(
 | 
	
		
			
				|  |  | +    void* arg, grpc_error* error) {
 | 
	
		
			
				|  |  | +  SecurityHandshaker* h = static_cast<SecurityHandshaker*>(arg);
 | 
	
		
			
				|  |  | +  grpc_core::ExecCtx::Run(
 | 
	
		
			
				|  |  | +      DEBUG_LOCATION,
 | 
	
		
			
				|  |  | +      GRPC_CLOSURE_INIT(&h->on_handshake_data_sent_to_peer_,
 | 
	
		
			
				|  |  | +                        &SecurityHandshaker::OnHandshakeDataSentToPeerFn, h,
 | 
	
		
			
				|  |  | +                        grpc_schedule_on_exec_ctx),
 | 
	
		
			
				|  |  | +      GRPC_ERROR_REF(error));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void SecurityHandshaker::OnHandshakeDataSentToPeerFn(void* arg,
 | 
	
		
			
				|  |  |                                                       grpc_error* error) {
 | 
	
		
			
				|  |  |    RefCountedPtr<SecurityHandshaker> h(static_cast<SecurityHandshaker*>(arg));
 | 
	
	
		
			
				|  | @@ -413,7 +433,13 @@ void SecurityHandshaker::OnHandshakeDataSentToPeerFn(void* arg,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    // We may be done.
 | 
	
		
			
				|  |  |    if (h->handshaker_result_ == nullptr) {
 | 
	
		
			
				|  |  | -    ExecCtx::Run(DEBUG_LOCATION, &h->schedule_read_closure_, GRPC_ERROR_NONE);
 | 
	
		
			
				|  |  | +    grpc_endpoint_read(
 | 
	
		
			
				|  |  | +        h->args_->endpoint, h->args_->read_buffer,
 | 
	
		
			
				|  |  | +        GRPC_CLOSURE_INIT(
 | 
	
		
			
				|  |  | +            &h->on_handshake_data_received_from_peer_,
 | 
	
		
			
				|  |  | +            &SecurityHandshaker::OnHandshakeDataReceivedFromPeerFnScheduler,
 | 
	
		
			
				|  |  | +            h.get(), grpc_schedule_on_exec_ctx),
 | 
	
		
			
				|  |  | +        /*urgent=*/true);
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  |      error = h->CheckPeerLocked();
 | 
	
		
			
				|  |  |      if (error != GRPC_ERROR_NONE) {
 |