|  | @@ -78,6 +78,7 @@ typedef struct grpc_rb_channel {
 | 
	
		
			
				|  |  |    grpc_connectivity_state current_connectivity_state;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    int mu_init_done;
 | 
	
		
			
				|  |  | +  int abort_watch_connectivity_state;
 | 
	
		
			
				|  |  |    gpr_mu channel_mu;
 | 
	
		
			
				|  |  |    gpr_cv channel_cv;
 | 
	
		
			
				|  |  |  } grpc_rb_channel;
 | 
	
	
		
			
				|  | @@ -193,6 +194,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
 | 
	
		
			
				|  |  |    wrapper->mu_init_done = 1;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    gpr_mu_lock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | +  wrapper->abort_watch_connectivity_state = 0;
 | 
	
		
			
				|  |  |    wrapper->current_connectivity_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0);
 | 
	
		
			
				|  |  |    wrapper->safe_to_destroy = 0;
 | 
	
		
			
				|  |  |    wrapper->request_safe_destroy = 0;
 | 
	
	
		
			
				|  | @@ -242,8 +244,7 @@ static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv,
 | 
	
		
			
				|  |  |      rb_raise(rb_eRuntimeError, "closed!");
 | 
	
		
			
				|  |  |      return Qnil;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return LONG2NUM(
 | 
	
		
			
				|  |  | -      grpc_channel_check_connectivity_state(ch, grpc_try_to_connect));
 | 
	
		
			
				|  |  | +  return LONG2NUM(grpc_channel_check_connectivity_state(wrapper->wrapped, grpc_try_to_connect));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  typedef struct watch_state_stack {
 | 
	
	
		
			
				|  | @@ -254,39 +255,35 @@ typedef struct watch_state_stack {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void *watch_channel_state_without_gvl(void *arg) {
 | 
	
		
			
				|  |  |    watch_state_stack *stack = (watch_state_stack*)arg;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    gpr_timespec deadline = stack->deadline;
 | 
	
		
			
				|  |  |    grpc_rb_channel *wrapper = stack->wrapper;
 | 
	
		
			
				|  |  |    int last_state = stack->last_state;
 | 
	
		
			
				|  |  | +  void *return_value = (void*)0;
 | 
	
		
			
				|  |  | +  gpr_timespec time_check_increment = gpr_time_add(
 | 
	
		
			
				|  |  | +    gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(20, GPR_TIMESPAN));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    gpr_mu_lock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | -  if (wrapper->current_connectivity_state != last_state) {
 | 
	
		
			
				|  |  | -    gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | -    return (void*)0;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if (wrapper->request_safe_destroy) {
 | 
	
		
			
				|  |  | -    gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | -    return (void*)0;
 | 
	
		
			
				|  |  | +  while(wrapper->current_connectivity_state == last_state &&
 | 
	
		
			
				|  |  | +        !wrapper->request_safe_destroy &&
 | 
	
		
			
				|  |  | +        !wrapper->safe_to_destroy &&
 | 
	
		
			
				|  |  | +        !wrapper->abort_watch_connectivity_state &&
 | 
	
		
			
				|  |  | +        gpr_time_cmp(deadline, gpr_now(GPR_CLOCK_REALTIME)) > 0) {
 | 
	
		
			
				|  |  | +    gpr_cv_wait(&wrapper->channel_cv, &wrapper->channel_mu, time_check_increment);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (wrapper->safe_to_destroy) {
 | 
	
		
			
				|  |  | -    gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | -    return (void*)0;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  gpr_cv_wait(&wrapper->channel_cv, &wrapper->channel_mu, deadline);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    if (wrapper->current_connectivity_state != last_state) {
 | 
	
		
			
				|  |  | -    gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | -    return (void*)1;
 | 
	
		
			
				|  |  | +    return_value = (void*)1;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | -  return (void*)0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  return return_value;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void watch_channel_state_unblocking_func(void *arg) {
 | 
	
		
			
				|  |  |    grpc_rb_channel *wrapper = (grpc_rb_channel*)arg;
 | 
	
		
			
				|  |  |    gpr_log(GPR_DEBUG, "GRPC_RUBY: watch channel state unblocking func called");
 | 
	
		
			
				|  |  |    gpr_mu_lock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | +  wrapper->abort_watch_connectivity_state = 1;
 | 
	
		
			
				|  |  |    gpr_cv_broadcast(&wrapper->channel_cv);
 | 
	
		
			
				|  |  |    gpr_mu_unlock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -461,8 +458,9 @@ static void grpc_rb_channel_try_register_connection_polling(
 | 
	
		
			
				|  |  |  // Note requires wrapper->wrapped, wrapper->channel_mu/cv initialized
 | 
	
		
			
				|  |  |  static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper) {
 | 
	
		
			
				|  |  |    gpr_mu_lock(&wrapper->channel_mu);
 | 
	
		
			
				|  |  | +  wrapper->request_safe_destroy = 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    while (!wrapper->safe_to_destroy) {
 | 
	
		
			
				|  |  | -    wrapper->request_safe_destroy = 1;
 | 
	
		
			
				|  |  |      gpr_cv_wait(&wrapper->channel_cv, &wrapper->channel_mu,
 | 
	
		
			
				|  |  |                  gpr_inf_future(GPR_CLOCK_REALTIME));
 | 
	
		
			
				|  |  |    }
 |