From d7455abfbd1394a6984b901a305785e9cba7b2d6 Mon Sep 17 00:00:00 2001
From: Alexander Polcyn <apolcyn@google.com>
Date: Wed, 17 May 2017 21:39:09 -0700
Subject: [PATCH] make get conn state always safe to call

---
 .../multiple_killed_watching_threads_driver.rb       |  7 +++++++
 src/ruby/ext/grpc/rb_channel.c                       | 12 ++++--------
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/src/ruby/end2end/multiple_killed_watching_threads_driver.rb b/src/ruby/end2end/multiple_killed_watching_threads_driver.rb
index 0c98915b7e..206ec8e801 100755
--- a/src/ruby/end2end/multiple_killed_watching_threads_driver.rb
+++ b/src/ruby/end2end/multiple_killed_watching_threads_driver.rb
@@ -46,10 +46,17 @@ def watch_state(ch)
 end
 
 def main
+  channels = []
   10.times do
     ch = GRPC::Core::Channel.new('dummy_host',
                                  nil, :this_channel_is_insecure)
     watch_state(ch)
+    channels << ch
+  end
+
+  # checking state should still be safe to call
+  channels.each do |c|
+    fail unless c.connectivity_state(false) == FATAL_FAILURE
   end
 end
 
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index 6e7baa3122..0524c49710 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -273,7 +273,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
 }
 
 typedef struct get_state_stack {
-  grpc_channel *channel;
+  bg_watched_channel *bg;
   int try_to_connect;
   int out;
 } get_state_stack;
@@ -283,14 +283,10 @@ static void *get_state_without_gil(void *arg) {
 
   gpr_mu_lock(&global_connection_polling_mu);
   GPR_ASSERT(abort_channel_polling || channel_polling_thread_started);
-  if (abort_channel_polling) {
-    // Assume that this channel has been destroyed by the
-    // background thread.
-    // The case in which the channel polling thread
-    // failed to start just always shows shutdown state.
+  if (stack->bg->channel_destroyed) {
     stack->out = GRPC_CHANNEL_SHUTDOWN;
   } else {
-    stack->out = grpc_channel_check_connectivity_state(stack->channel,
+    stack->out = grpc_channel_check_connectivity_state(stack->bg->channel,
                                                        stack->try_to_connect);
   }
   gpr_mu_unlock(&global_connection_polling_mu);
@@ -322,7 +318,7 @@ static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv,
     return Qnil;
   }
 
-  stack.channel = wrapper->bg_wrapped->channel;
+  stack.bg = wrapper->bg_wrapped;
   stack.try_to_connect = RTEST(try_to_connect_param) ? 1 : 0;
   rb_thread_call_without_gvl(get_state_without_gil, &stack, NULL, NULL);
 
-- 
GitLab