|  | @@ -184,11 +184,13 @@ struct transport {
 | 
	
		
			
				|  |  |    gpr_uint8 is_client;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    gpr_mu mu;
 | 
	
		
			
				|  |  | +  gpr_cv cv;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* basic state management - what are we doing at the moment? */
 | 
	
		
			
				|  |  |    gpr_uint8 reading;
 | 
	
		
			
				|  |  |    gpr_uint8 writing;
 | 
	
		
			
				|  |  |    gpr_uint8 calling_back;
 | 
	
		
			
				|  |  | +  gpr_uint8 destroying;
 | 
	
		
			
				|  |  |    error_state error_state;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* stream indexing */
 | 
	
	
		
			
				|  | @@ -362,6 +364,7 @@ static void unref_transport(transport *t) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    gpr_mu_unlock(&t->mu);
 | 
	
		
			
				|  |  |    gpr_mu_destroy(&t->mu);
 | 
	
		
			
				|  |  | +  gpr_cv_destroy(&t->cv);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* callback remaining pings: they're not allowed to call into the transpot,
 | 
	
		
			
				|  |  |       and maybe they hold resources that need to be freed */
 | 
	
	
		
			
				|  | @@ -397,6 +400,7 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup,
 | 
	
		
			
				|  |  |    /* one ref is for destroy, the other for when ep becomes NULL */
 | 
	
		
			
				|  |  |    gpr_ref_init(&t->refs, 2);
 | 
	
		
			
				|  |  |    gpr_mu_init(&t->mu);
 | 
	
		
			
				|  |  | +  gpr_cv_init(&t->cv);
 | 
	
		
			
				|  |  |    t->metadata_context = mdctx;
 | 
	
		
			
				|  |  |    t->str_grpc_timeout =
 | 
	
		
			
				|  |  |        grpc_mdstr_from_string(t->metadata_context, "grpc-timeout");
 | 
	
	
		
			
				|  | @@ -405,6 +409,7 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup,
 | 
	
		
			
				|  |  |    t->error_state = ERROR_STATE_NONE;
 | 
	
		
			
				|  |  |    t->next_stream_id = is_client ? 1 : 2;
 | 
	
		
			
				|  |  |    t->last_incoming_stream_id = 0;
 | 
	
		
			
				|  |  | +  t->destroying = 0;
 | 
	
		
			
				|  |  |    t->is_client = is_client;
 | 
	
		
			
				|  |  |    t->outgoing_window = DEFAULT_WINDOW;
 | 
	
		
			
				|  |  |    t->incoming_window = DEFAULT_WINDOW;
 | 
	
	
		
			
				|  | @@ -487,6 +492,7 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup,
 | 
	
		
			
				|  |  |    t->cb = sr.callbacks;
 | 
	
		
			
				|  |  |    t->cb_user_data = sr.user_data;
 | 
	
		
			
				|  |  |    t->calling_back = 0;
 | 
	
		
			
				|  |  | +  if (t->destroying) gpr_cv_signal(&t->cv);
 | 
	
		
			
				|  |  |    unlock(t);
 | 
	
		
			
				|  |  |    unref_transport(t);
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -495,6 +501,10 @@ static void destroy_transport(grpc_transport *gt) {
 | 
	
		
			
				|  |  |    transport *t = (transport *)gt;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    gpr_mu_lock(&t->mu);
 | 
	
		
			
				|  |  | +  t->destroying = 1;
 | 
	
		
			
				|  |  | +  while (t->calling_back) {
 | 
	
		
			
				|  |  | +    gpr_cv_wait(&t->cv, &t->mu, gpr_inf_future);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    t->cb = NULL;
 | 
	
		
			
				|  |  |    gpr_mu_unlock(&t->mu);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -754,6 +764,7 @@ static void unlock(transport *t) {
 | 
	
		
			
				|  |  |    if (perform_callbacks || call_closed || num_goaways) {
 | 
	
		
			
				|  |  |      lock(t);
 | 
	
		
			
				|  |  |      t->calling_back = 0;
 | 
	
		
			
				|  |  | +    if (t->destroying) gpr_cv_signal(&t->cv);
 | 
	
		
			
				|  |  |      unlock(t);
 | 
	
		
			
				|  |  |      unref_transport(t);
 | 
	
		
			
				|  |  |    }
 |