|  | @@ -89,6 +89,8 @@ typedef struct grpc_rb_channel {
 | 
	
		
			
				|  |  |  static void grpc_rb_channel_try_register_connection_polling(
 | 
	
		
			
				|  |  |      grpc_rb_channel *wrapper);
 | 
	
		
			
				|  |  |  static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper);
 | 
	
		
			
				|  |  | +static void *wait_until_channel_polling_thread_started_no_gil(void*);
 | 
	
		
			
				|  |  | +static void wait_until_channel_polling_thread_started_unblocking_func(void*);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static grpc_completion_queue *channel_polling_cq;
 | 
	
		
			
				|  |  |  static gpr_mu global_connection_polling_mu;
 | 
	
	
		
			
				|  | @@ -169,6 +171,8 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
 | 
	
		
			
				|  |  |    MEMZERO(&args, grpc_channel_args, 1);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    grpc_ruby_once_init();
 | 
	
		
			
				|  |  | +  rb_thread_call_without_gvl(wait_until_channel_polling_thread_started_no_gil, NULL,
 | 
	
		
			
				|  |  | +                             wait_until_channel_polling_thread_started_unblocking_func, NULL);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* "3" == 3 mandatory args */
 | 
	
		
			
				|  |  |    rb_scan_args(argc, argv, "3", &target, &channel_args, &credentials);
 | 
	
	
		
			
				|  | @@ -440,6 +444,7 @@ static void grpc_rb_channel_try_register_connection_polling(
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    gpr_mu_lock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  GPR_ASSERT(channel_polling_thread_started || abort_channel_polling);
 | 
	
		
			
				|  |  |    conn_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0);
 | 
	
		
			
				|  |  |    if (conn_state != wrapper->current_connectivity_state) {
 | 
	
		
			
				|  |  |      wrapper->current_connectivity_state = conn_state;
 | 
	
	
		
			
				|  | @@ -473,7 +478,7 @@ static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Note this loop breaks out with a single call of
 | 
	
		
			
				|  |  | -// "grpc_rb_event_unblocking_func".
 | 
	
		
			
				|  |  | +// "run_poll_channels_loop_no_gil".
 | 
	
		
			
				|  |  |  // This assumes that a ruby call the unblocking func
 | 
	
		
			
				|  |  |  // indicates process shutdown.
 | 
	
		
			
				|  |  |  // In the worst case, this stops polling channel connectivity
 | 
	
	
		
			
				|  | @@ -486,7 +491,7 @@ static void *run_poll_channels_loop_no_gil(void *arg) {
 | 
	
		
			
				|  |  |    gpr_mu_lock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  |    GPR_ASSERT(!channel_polling_thread_started);
 | 
	
		
			
				|  |  |    channel_polling_thread_started = 1;
 | 
	
		
			
				|  |  | -  gpr_cv_signal(&global_connection_polling_cv);
 | 
	
		
			
				|  |  | +  gpr_cv_broadcast(&global_connection_polling_cv);
 | 
	
		
			
				|  |  |    gpr_mu_unlock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    for (;;) {
 | 
	
	
		
			
				|  | @@ -505,10 +510,10 @@ static void *run_poll_channels_loop_no_gil(void *arg) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Notify the channel polling loop to cleanup and shutdown.
 | 
	
		
			
				|  |  | -static void grpc_rb_event_unblocking_func(void *arg) {
 | 
	
		
			
				|  |  | +static void run_poll_channels_loop_unblocking_func(void *arg) {
 | 
	
		
			
				|  |  |    (void)arg;
 | 
	
		
			
				|  |  |    gpr_mu_lock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  | -  gpr_log(GPR_DEBUG, "GRPC_RUBY: grpc_rb_event_unblocking_func - begin aborting connection polling");
 | 
	
		
			
				|  |  | +  gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_unblocking_func - begin aborting connection polling");
 | 
	
		
			
				|  |  |    abort_channel_polling = 1;
 | 
	
		
			
				|  |  |    grpc_completion_queue_shutdown(channel_polling_cq);
 | 
	
		
			
				|  |  |    gpr_mu_unlock(&global_connection_polling_mu);
 | 
	
	
		
			
				|  | @@ -519,12 +524,12 @@ 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);
 | 
	
		
			
				|  |  | +                             run_poll_channels_loop_unblocking_func, NULL);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    return Qnil;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void *grpc_rb_wait_until_channel_polling_thread_started(void *arg) {
 | 
	
		
			
				|  |  | +static void *wait_until_channel_polling_thread_started_no_gil(void *arg) {
 | 
	
		
			
				|  |  |    (void)arg;
 | 
	
		
			
				|  |  |    gpr_log(GPR_DEBUG, "GRPC_RUBY: wait for channel polling thread to start");
 | 
	
		
			
				|  |  |    gpr_mu_lock(&global_connection_polling_mu);
 | 
	
	
		
			
				|  | @@ -537,6 +542,14 @@ static void *grpc_rb_wait_until_channel_polling_thread_started(void *arg) {
 | 
	
		
			
				|  |  |    return NULL;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static void wait_until_channel_polling_thread_started_unblocking_func(void* arg) {
 | 
	
		
			
				|  |  | +  (void)arg;
 | 
	
		
			
				|  |  | +  gpr_mu_lock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  | +  gpr_log(GPR_DEBUG, "GRPC_RUBY: wait_until_channel_polling_thread_started_unblocking_func - begin aborting connection polling");
 | 
	
		
			
				|  |  | +  abort_channel_polling = 1;
 | 
	
		
			
				|  |  | +  gpr_cv_broadcast(&global_connection_polling_cv);
 | 
	
		
			
				|  |  | +  gpr_mu_unlock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* Temporary fix for
 | 
	
		
			
				|  |  |   * https://github.com/GoogleCloudPlatform/google-cloud-ruby/issues/899.
 | 
	
	
		
			
				|  | @@ -565,14 +578,9 @@ void grpc_rb_channel_polling_thread_start() {
 | 
	
		
			
				|  |  |      gpr_log(GPR_DEBUG, "GRPC_RUBY: failed to spawn channel polling thread");
 | 
	
		
			
				|  |  |      gpr_mu_lock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  |      abort_channel_polling = 1;
 | 
	
		
			
				|  |  | +    gpr_cv_broadcast(&global_connection_polling_cv);
 | 
	
		
			
				|  |  |      gpr_mu_unlock(&global_connection_polling_mu);
 | 
	
		
			
				|  |  | -    return;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Drop the gil before sleeping on a gpr_cv so that the background thread
 | 
	
		
			
				|  |  | -  // signaling it can acquire the gil and then start, if it hasn't already.
 | 
	
		
			
				|  |  | -  rb_thread_call_without_gvl(grpc_rb_wait_until_channel_polling_thread_started, NULL,
 | 
	
		
			
				|  |  | -                             grpc_rb_event_unblocking_func, NULL);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void Init_grpc_propagate_masks() {
 |