From 19bf00b69b665523607b972a8ec86fda04bbd5f4 Mon Sep 17 00:00:00 2001
From: murgatroid99 <mlumish@google.com>
Date: Tue, 17 May 2016 18:22:01 -0700
Subject: [PATCH] Re-added signal handlers to cancel calls and shut down
 servers

---
 src/ruby/lib/grpc.rb                     |  3 ++
 src/ruby/lib/grpc/generic/active_call.rb |  5 ++
 src/ruby/lib/grpc/generic/rpc_server.rb  |  4 ++
 src/ruby/lib/grpc/signals.rb             | 68 ++++++++++++++++++++++++
 4 files changed, 80 insertions(+)
 create mode 100644 src/ruby/lib/grpc/signals.rb

diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb
index 79fa705b1c..ab21fc4772 100644
--- a/src/ruby/lib/grpc.rb
+++ b/src/ruby/lib/grpc.rb
@@ -33,6 +33,7 @@ require_relative 'grpc/errors'
 require_relative 'grpc/grpc'
 require_relative 'grpc/logconfig'
 require_relative 'grpc/notifier'
+require_relative 'grpc/signals'
 require_relative 'grpc/version'
 require_relative 'grpc/core/time_consts'
 require_relative 'grpc/generic/active_call'
@@ -47,3 +48,5 @@ begin
 ensure
   file.close
 end
+
+GRPC::Signals.init
diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb
index 7fe588bd4c..f91970a923 100644
--- a/src/ruby/lib/grpc/generic/active_call.rb
+++ b/src/ruby/lib/grpc/generic/active_call.rb
@@ -30,6 +30,7 @@
 require 'forwardable'
 require 'weakref'
 require_relative 'bidi_call'
+require_relative '../signals'
 
 class Struct
   # BatchResult is the struct returned by calls to call#start_batch.
@@ -122,6 +123,10 @@ module GRPC
       @unmarshal = unmarshal
       @metadata_tag = metadata_tag
       @op_notifier = nil
+      weak_self = WeakRef.new(self)
+      signal_handler = proc { weak_self.cancel if weak_self.weakref_alive? }
+      remove_handler = GRPC::Signals.register_handler(&signal_handler)
+      ObjectSpace.define_finalizer(self, remove_handler)
     end
 
     # output_metadata are provides access to hash that can be used to
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index e1496d491a..238aaa9656 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -28,6 +28,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 require_relative '../grpc'
+require_relative '../signals'
 require_relative 'active_call'
 require_relative 'service'
 require 'thread'
@@ -352,7 +353,10 @@ module GRPC
         transition_running_state(:running)
         @run_cond.broadcast
       end
+      remove_signal_handler = GRPC::Signals.register_handler { stop }
       loop_handle_server_calls
+      # Remove signal handler when server stops
+      remove_signal_handler.call
     end
 
     alias_method :run_till_terminated, :run
diff --git a/src/ruby/lib/grpc/signals.rb b/src/ruby/lib/grpc/signals.rb
new file mode 100644
index 0000000000..56bc9f32a0
--- /dev/null
+++ b/src/ruby/lib/grpc/signals.rb
@@ -0,0 +1,68 @@
+# Copyright 2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+require 'thread'
+require_relative 'grpc'
+
+# GRPC contains the General RPC module.
+module GRPC
+  # Signals contains gRPC functions related to signal handling
+  module Signals
+    @signal_handlers = []
+    @handlers_mutex = Mutex.new
+    @previous_handlers = {}
+    # @signal_received = false
+
+    def register_handler(&handler)
+      @handlers_mutex.synchronize do
+        @signal_handlers.push(handler)
+        # handler.call if @signal_received
+      end
+      # Returns a function to remove the handler
+      lambda do
+        @handlers_mutex.synchronize { @signal_handlers.delete(handler) }
+      end
+    end
+    module_function :register_handler
+
+    def run_handlers(signal)
+      # @signal_received = true
+      @signal_handlers.each(&:call)
+      @previous_handlers[signal].call
+    end
+    module_function :run_handlers
+
+    def init
+      %w(INT TERM).each do |sig|
+        @previous_handlers[sig] = Signal.trap(sig) { run_handlers(sig) }
+      end
+    end
+    module_function :init
+  end
+end
-- 
GitLab