|  | @@ -89,7 +89,7 @@ static void grpc_rb_channel_try_register_connection_polling(
 | 
	
		
			
				|  |  |  static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static grpc_completion_queue *channel_polling_cq;
 | 
	
		
			
				|  |  | -static gpr_mu channel_polling_mu;
 | 
	
		
			
				|  |  | +static gpr_mu global_connection_polling_mu;
 | 
	
		
			
				|  |  |  static int abort_channel_polling = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* Destroys Channel instances. */
 | 
	
	
		
			
				|  | @@ -188,13 +188,13 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    gpr_mu_lock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  |    wrapper->current_connectivity_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0);
 | 
	
		
			
				|  |  | -  gpr_cv_signal(&wrapper->channel_cv);
 | 
	
		
			
				|  |  | -  gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  gpr_mu_lock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  |    wrapper->safe_to_destroy = 0;
 | 
	
		
			
				|  |  |    wrapper->request_safe_destroy = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  gpr_cv_signal(&wrapper->channel_cv);
 | 
	
		
			
				|  |  |    gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    grpc_rb_channel_try_register_connection_polling(wrapper);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (args.args != NULL) {
 | 
	
	
		
			
				|  | @@ -277,7 +277,6 @@ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    if (wrapper->safe_to_destroy) {
 | 
	
		
			
				|  |  |      gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | -    gpr_log(GPR_DEBUG, "GRPC_RUBY_RB_CHANNEL: attempt to watch_connectivity_state on a non-state-polled channel");
 | 
	
		
			
				|  |  |      return Qfalse;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    gpr_cv_wait(&wrapper->channel_cv, &wrapper->channel_mu, grpc_rb_time_timeval(deadline, /* absolute time */ 0));
 | 
	
	
		
			
				|  | @@ -394,7 +393,7 @@ static VALUE grpc_rb_channel_get_target(VALUE self) {
 | 
	
		
			
				|  |  |  // destroy.
 | 
	
		
			
				|  |  |  // Not safe to call while a channel's connection state is polled.
 | 
	
		
			
				|  |  |  static void grpc_rb_channel_try_register_connection_polling(
 | 
	
		
			
				|  |  | -    grpc_rb_channel *wrapper) {
 | 
	
		
			
				|  |  | +  grpc_rb_channel *wrapper) {
 | 
	
		
			
				|  |  |    grpc_connectivity_state conn_state;
 | 
	
		
			
				|  |  |    gpr_timespec sleep_time = gpr_time_add(
 | 
	
		
			
				|  |  |        gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(20, GPR_TIMESPAN));
 | 
	
	
		
			
				|  | @@ -408,9 +407,8 @@ static void grpc_rb_channel_try_register_connection_polling(
 | 
	
		
			
				|  |  |      gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  |      return;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  gpr_mu_lock(&channel_polling_mu);
 | 
	
		
			
				|  |  | +  gpr_mu_lock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  gpr_mu_lock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  |    conn_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0);
 | 
	
		
			
				|  |  |    if (conn_state != wrapper->current_connectivity_state) {
 | 
	
		
			
				|  |  |      wrapper->current_connectivity_state = conn_state;
 | 
	
	
		
			
				|  | @@ -424,8 +422,7 @@ static void grpc_rb_channel_try_register_connection_polling(
 | 
	
		
			
				|  |  |      wrapper->safe_to_destroy = 1;
 | 
	
		
			
				|  |  |      gpr_cv_signal(&wrapper->channel_cv);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | -  gpr_mu_unlock(&channel_polling_mu);
 | 
	
		
			
				|  |  | +  gpr_mu_unlock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  |    gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -454,7 +451,6 @@ static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper) {
 | 
	
		
			
				|  |  |  // early and falls back to current behavior.
 | 
	
		
			
				|  |  |  static void *run_poll_channels_loop_no_gil(void *arg) {
 | 
	
		
			
				|  |  |    grpc_event event;
 | 
	
		
			
				|  |  | -  grpc_rb_channel *wrapper;
 | 
	
		
			
				|  |  |    (void)arg;
 | 
	
		
			
				|  |  |    for (;;) {
 | 
	
		
			
				|  |  |      event = grpc_completion_queue_next(
 | 
	
	
		
			
				|  | @@ -463,27 +459,28 @@ static void *run_poll_channels_loop_no_gil(void *arg) {
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      if (event.type == GRPC_OP_COMPLETE) {
 | 
	
		
			
				|  |  | -      wrapper = (grpc_rb_channel *)event.tag;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      grpc_rb_channel_try_register_connection_polling(wrapper);
 | 
	
		
			
				|  |  | +      grpc_rb_channel_try_register_connection_polling((grpc_rb_channel *)event.tag);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    grpc_completion_queue_destroy(channel_polling_cq);
 | 
	
		
			
				|  |  | +  gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_no_gil - exit connection polling loop");
 | 
	
		
			
				|  |  |    return NULL;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Notify the channel polling loop to cleanup and shutdown.
 | 
	
		
			
				|  |  |  static void grpc_rb_event_unblocking_func(void *arg) {
 | 
	
		
			
				|  |  |    (void)arg;
 | 
	
		
			
				|  |  | -  gpr_mu_lock(&channel_polling_mu);
 | 
	
		
			
				|  |  | +  gpr_mu_lock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  | +  gpr_log(GPR_DEBUG, "GRPC_RUBY: grpc_rb_event_unblocking_func - begin aborting connection polling");
 | 
	
		
			
				|  |  |    abort_channel_polling = 1;
 | 
	
		
			
				|  |  |    grpc_completion_queue_shutdown(channel_polling_cq);
 | 
	
		
			
				|  |  | -  gpr_mu_unlock(&channel_polling_mu);
 | 
	
		
			
				|  |  | +  gpr_mu_unlock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Poll channel connectivity states in background thread without the GIL.
 | 
	
		
			
				|  |  |  static VALUE run_poll_channels_loop(VALUE arg) {
 | 
	
		
			
				|  |  |    (void)arg;
 | 
	
		
			
				|  |  | +  gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop - create connection polling thread");
 | 
	
		
			
				|  |  |    rb_thread_call_without_gvl(run_poll_channels_loop_no_gil, NULL,
 | 
	
		
			
				|  |  |                               grpc_rb_event_unblocking_func, NULL);
 | 
	
		
			
				|  |  |    return Qnil;
 | 
	
	
		
			
				|  | @@ -501,7 +498,7 @@ static VALUE run_poll_channels_loop(VALUE arg) {
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  static void start_poll_channels_loop() {
 | 
	
		
			
				|  |  |    channel_polling_cq = grpc_completion_queue_create(NULL);
 | 
	
		
			
				|  |  | -  gpr_mu_init(&channel_polling_mu);
 | 
	
		
			
				|  |  | +  gpr_mu_init(&global_connection_polling_mu);
 | 
	
		
			
				|  |  |    abort_channel_polling = 0;
 | 
	
		
			
				|  |  |    rb_thread_create(run_poll_channels_loop, NULL);
 | 
	
		
			
				|  |  |  }
 |