From 9161a82565a0bdaf4622f7f8c8e967d29e904a9c Mon Sep 17 00:00:00 2001
From: Tim Emiola <temiola@google.com>
Date: Wed, 11 Nov 2015 15:58:44 -0800
Subject: [PATCH] Corrects compile error on ruby 2.0

---
 src/ruby/ext/grpc/rb_call.c               | 15 +++++++++++++--
 src/ruby/ext/grpc/rb_channel.c            |  2 ++
 src/ruby/ext/grpc/rb_channel_args.c       |  2 ++
 src/ruby/ext/grpc/rb_completion_queue.c   |  4 +++-
 src/ruby/ext/grpc/rb_credentials.c        |  5 ++++-
 src/ruby/ext/grpc/rb_grpc.c               | 20 +++++++++++++++++++-
 src/ruby/ext/grpc/rb_server.c             |  5 ++++-
 src/ruby/ext/grpc/rb_server_credentials.c |  2 ++
 8 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index 6b5beb6f5d..40364328ee 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -139,7 +139,15 @@ static const rb_data_type_t grpc_rb_md_ary_data_type = {
      {NULL, NULL}},
     NULL,
     NULL,
-    0};
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
+    /* it is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because
+     * grpc_rb_call_destroy
+     * touches a hash object.
+     * TODO(yugui) Directly use st_table and call the free function earlier?
+     */
+    0,
+#endif
+};
 
 /* Describes grpc_call struct for RTypedData */
 static const rb_data_type_t grpc_call_data_type = {
@@ -148,12 +156,15 @@ static const rb_data_type_t grpc_call_data_type = {
      {NULL, NULL}},
     NULL,
     NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     /* it is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because
      * grpc_rb_call_destroy
      * touches a hash object.
      * TODO(yugui) Directly use st_table and call the free function earlier?
      */
-    0};
+    0,
+#endif
+};
 
 /* Error code details is a hash containing text strings describing errors */
 VALUE rb_error_code_details;
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index 90afdc3fe1..cd0b966e72 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -111,7 +111,9 @@ static rb_data_type_t grpc_channel_data_type = {
     {grpc_rb_channel_mark, grpc_rb_channel_free, GRPC_RB_MEMSIZE_UNAVAILABLE,
      {NULL, NULL}},
     NULL, NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     RUBY_TYPED_FREE_IMMEDIATELY
+#endif
 };
 
 /* Allocates grpc_rb_channel instances. */
diff --git a/src/ruby/ext/grpc/rb_channel_args.c b/src/ruby/ext/grpc/rb_channel_args.c
index 1ba30b69aa..37dd981925 100644
--- a/src/ruby/ext/grpc/rb_channel_args.c
+++ b/src/ruby/ext/grpc/rb_channel_args.c
@@ -44,7 +44,9 @@ static rb_data_type_t grpc_rb_channel_args_data_type = {
     {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, GRPC_RB_MEMSIZE_UNAVAILABLE,
      {NULL, NULL}},
     NULL, NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     RUBY_TYPED_FREE_IMMEDIATELY
+#endif
 };
 
 /* A callback the processes the hash key values in channel_args hash */
diff --git a/src/ruby/ext/grpc/rb_completion_queue.c b/src/ruby/ext/grpc/rb_completion_queue.c
index 0bc9eb2a97..a7de96d718 100644
--- a/src/ruby/ext/grpc/rb_completion_queue.c
+++ b/src/ruby/ext/grpc/rb_completion_queue.c
@@ -121,9 +121,11 @@ static rb_data_type_t grpc_rb_completion_queue_data_type = {
     {GRPC_RB_GC_NOT_MARKED, grpc_rb_completion_queue_destroy,
      GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}},
     NULL, NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     /* cannot immediately free because grpc_rb_completion_queue_shutdown_drain
      * calls rb_thread_call_without_gvl. */
-    0
+    0,
+#endif
 };
 
 /* Allocates a completion queue. */
diff --git a/src/ruby/ext/grpc/rb_credentials.c b/src/ruby/ext/grpc/rb_credentials.c
index ae757f6986..486ff79f91 100644
--- a/src/ruby/ext/grpc/rb_credentials.c
+++ b/src/ruby/ext/grpc/rb_credentials.c
@@ -92,7 +92,10 @@ static rb_data_type_t grpc_rb_credentials_data_type = {
      GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}},
     NULL,
     NULL,
-    RUBY_TYPED_FREE_IMMEDIATELY};
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
+    RUBY_TYPED_FREE_IMMEDIATELY
+#endif
+};
 
 /* Allocates Credential instances.
    Provides safe initial defaults for the instance fields. */
diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c
index 327fd1a4fc..33f48779d8 100644
--- a/src/ruby/ext/grpc/rb_grpc.c
+++ b/src/ruby/ext/grpc/rb_grpc.c
@@ -55,7 +55,10 @@ static rb_data_type_t grpc_rb_timespec_data_type = {
      {NULL, NULL}},
     NULL,
     NULL,
-    RUBY_TYPED_FREE_IMMEDIATELY};
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
+    RUBY_TYPED_FREE_IMMEDIATELY
+#endif
+};
 
 /* Alloc func that blocks allocation of a given object by raising an
  * exception. */
@@ -262,10 +265,20 @@ static void Init_grpc_time_consts() {
   id_tv_nsec = rb_intern("tv_nsec");
 }
 
+/*
+   TODO: find an alternative to ruby_vm_at_exit that is ok in Ruby 2.0 where
+   RUBY_TYPED_FREE_IMMEDIATELY is not defined.
+
+   At the moment, registering a function using ruby_vm_at_exit segfaults in Ruby
+   2.0.  This is not an issue with the gRPC handler.  More likely, this was an
+   in issue with 2.0 that got resolved in 2.1 and has not been backported.
+*/
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
 static void grpc_rb_shutdown(ruby_vm_t *vm) {
   (void)vm;
   grpc_shutdown();
 }
+#endif
 
 /* Initialize the GRPC module structs */
 
@@ -285,7 +298,12 @@ VALUE sym_metadata = Qundef;
 
 void Init_grpc() {
   grpc_init();
+
+/* TODO: find alternative to ruby_vm_at_exit that is ok in Ruby 2.0 */
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
   ruby_vm_at_exit(grpc_rb_shutdown);
+#endif
+
   grpc_rb_mGRPC = rb_define_module("GRPC");
   grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core");
   grpc_rb_sNewServerRpc =
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index 4469658869..ebdd7e1a34 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -101,11 +101,14 @@ static const rb_data_type_t grpc_rb_server_data_type = {
      {NULL, NULL}},
     NULL,
     NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     /* It is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because the free function would block
      * and we might want to unlock GVL
      * TODO(yugui) Unlock GVL?
      */
-    0};
+    0,
+#endif
+};
 
 /* Allocates grpc_rb_server instances. */
 static VALUE grpc_rb_server_alloc(VALUE cls) {
diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c
index ea4d0d864e..de57585e0b 100644
--- a/src/ruby/ext/grpc/rb_server_credentials.c
+++ b/src/ruby/ext/grpc/rb_server_credentials.c
@@ -91,7 +91,9 @@ static const rb_data_type_t grpc_rb_server_credentials_data_type = {
     {grpc_rb_server_credentials_mark, grpc_rb_server_credentials_free,
      GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}},
     NULL, NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     RUBY_TYPED_FREE_IMMEDIATELY
+#endif
 };
 
 /* Allocates ServerCredential instances.
-- 
GitLab