aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ruby
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2015-04-20 09:04:57 -0700
committerGravatar Craig Tiller <ctiller@google.com>2015-04-20 09:04:57 -0700
commitc8a2299fe88a2e9325e07e6a8579bdb07b85b349 (patch)
tree3298194be904f974fcbb64b1f155332c350b3725 /src/ruby
parent9c9d4e0cd9025f3ff7aaf7cacfd2e24dfd6aa58e (diff)
parentb572fcba35fd66cce102b29389a5892d3d45e651 (diff)
Merge github.com:grpc/grpc into batch-metadata
Diffstat (limited to 'src/ruby')
-rw-r--r--src/ruby/.rubocop_todo.yml8
-rwxr-xr-xsrc/ruby/bin/interop/interop_server.rb2
-rwxr-xr-xsrc/ruby/bin/math_server.rb2
-rwxr-xr-xsrc/ruby/bin/noproto_server.rb2
-rw-r--r--src/ruby/ext/grpc/rb_call.c50
-rw-r--r--src/ruby/ext/grpc/rb_channel.c22
-rw-r--r--src/ruby/ext/grpc/rb_channel_args.c15
-rw-r--r--src/ruby/ext/grpc/rb_completion_queue.c31
-rw-r--r--src/ruby/ext/grpc/rb_credentials.c47
-rw-r--r--src/ruby/ext/grpc/rb_grpc.c46
-rw-r--r--src/ruby/ext/grpc/rb_grpc.h8
-rw-r--r--src/ruby/ext/grpc/rb_server.c33
-rw-r--r--src/ruby/ext/grpc/rb_server_credentials.c24
-rwxr-xr-xsrc/ruby/grpc.gemspec6
-rw-r--r--src/ruby/lib/grpc/generic/client_stub.rb1
-rw-r--r--src/ruby/lib/grpc/generic/rpc_server.rb75
-rw-r--r--src/ruby/spec/credentials_spec.rb4
-rw-r--r--src/ruby/spec/generic/client_stub_spec.rb1
-rw-r--r--src/ruby/spec/generic/rpc_server_pool_spec.rb1
-rw-r--r--src/ruby/spec/generic/rpc_server_spec.rb1
20 files changed, 271 insertions, 108 deletions
diff --git a/src/ruby/.rubocop_todo.yml b/src/ruby/.rubocop_todo.yml
index b4d66c517c..02136a81a9 100644
--- a/src/ruby/.rubocop_todo.yml
+++ b/src/ruby/.rubocop_todo.yml
@@ -1,18 +1,18 @@
# This configuration was generated by `rubocop --auto-gen-config`
-# on 2015-04-15 18:43:23 -0700 using RuboCop version 0.30.0.
+# on 2015-04-16 12:30:09 -0700 using RuboCop version 0.30.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
-# Offense count: 32
+# Offense count: 34
Metrics/AbcSize:
Max: 36
# Offense count: 3
# Configuration parameters: CountComments.
Metrics/ClassLength:
- Max: 183
+ Max: 185
# Offense count: 35
# Configuration parameters: CountComments.
@@ -24,7 +24,7 @@ Metrics/MethodLength:
Metrics/ParameterLists:
Max: 8
-# Offense count: 6
+# Offense count: 9
# Configuration parameters: AllowedVariables.
Style/GlobalVars:
Enabled: false
diff --git a/src/ruby/bin/interop/interop_server.rb b/src/ruby/bin/interop/interop_server.rb
index 0819ba9bbc..72570d92f3 100755
--- a/src/ruby/bin/interop/interop_server.rb
+++ b/src/ruby/bin/interop/interop_server.rb
@@ -185,7 +185,7 @@ def main
logger.info("... running insecurely on #{host}")
end
s.handle(TestTarget)
- s.run
+ s.run_till_terminated
end
main
diff --git a/src/ruby/bin/math_server.rb b/src/ruby/bin/math_server.rb
index 5cc7613489..1bfe253b85 100755
--- a/src/ruby/bin/math_server.rb
+++ b/src/ruby/bin/math_server.rb
@@ -183,7 +183,7 @@ def main
end
s.handle(Calculator)
- s.run
+ s.run_till_terminated
end
main
diff --git a/src/ruby/bin/noproto_server.rb b/src/ruby/bin/noproto_server.rb
index 9979cb7ebb..f71daeadb3 100755
--- a/src/ruby/bin/noproto_server.rb
+++ b/src/ruby/bin/noproto_server.rb
@@ -105,7 +105,7 @@ def main
end
s.handle(NoProto)
- s.run
+ s.run_till_terminated
end
main
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index b0963411d1..6da7d3c830 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -117,6 +117,37 @@ static void grpc_rb_call_destroy(void *p) {
}
}
+static size_t md_ary_datasize(const void *p) {
+ const grpc_metadata_array* const ary = (grpc_metadata_array*)p;
+ size_t i, datasize = sizeof(grpc_metadata_array);
+ for (i = 0; i < ary->count; ++i) {
+ const grpc_metadata* const md = &ary->metadata[i];
+ datasize += strlen(md->key);
+ datasize += md->value_length;
+ }
+ datasize += ary->capacity * sizeof(grpc_metadata);
+ return datasize;
+}
+
+static const rb_data_type_t grpc_rb_md_ary_data_type = {
+ "grpc_metadata_array",
+ {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, md_ary_datasize},
+ NULL, NULL,
+ 0
+};
+
+/* Describes grpc_call struct for RTypedData */
+static const rb_data_type_t grpc_call_data_type = {
+ "grpc_call",
+ {GRPC_RB_GC_NOT_MARKED, grpc_rb_call_destroy, GRPC_RB_MEMSIZE_UNAVAILABLE},
+ NULL, NULL,
+ /* 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
+};
+
/* Error code details is a hash containing text strings describing errors */
VALUE rb_error_code_details;
@@ -135,7 +166,7 @@ const char *grpc_call_error_detail_of(grpc_call_error err) {
static VALUE grpc_rb_call_cancel(VALUE self) {
grpc_call *call = NULL;
grpc_call_error err;
- Data_Get_Struct(self, grpc_call, call);
+ TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
err = grpc_call_cancel(call);
if (err != GRPC_CALL_OK) {
rb_raise(grpc_rb_eCallError, "cancel failed: %s (code=%d)",
@@ -205,7 +236,8 @@ static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
int i;
/* Construct a metadata object from key and value and add it */
- Data_Get_Struct(md_ary_obj, grpc_metadata_array, md_ary);
+ TypedData_Get_Struct(md_ary_obj, grpc_metadata_array,
+ &grpc_rb_md_ary_data_type, md_ary);
if (TYPE(val) == T_ARRAY) {
/* If the value is an array, add capacity for each value in the array */
@@ -243,7 +275,8 @@ static int grpc_rb_md_ary_capacity_hash_cb(VALUE key, VALUE val,
grpc_metadata_array *md_ary = NULL;
/* Construct a metadata object from key and value and add it */
- Data_Get_Struct(md_ary_obj, grpc_metadata_array, md_ary);
+ TypedData_Get_Struct(md_ary_obj, grpc_metadata_array,
+ &grpc_rb_md_ary_data_type, md_ary);
if (TYPE(val) == T_ARRAY) {
/* If the value is an array, add capacity for each value in the array */
@@ -270,8 +303,8 @@ static void grpc_rb_md_ary_convert(VALUE md_ary_hash, grpc_metadata_array *md_ar
/* Initialize the array, compute it's capacity, then fill it. */
grpc_metadata_array_init(md_ary);
- md_ary_obj =
- Data_Wrap_Struct(grpc_rb_cMdAry, GC_NOT_MARKED, GC_DONT_FREE, md_ary);
+ md_ary_obj = TypedData_Wrap_Struct(grpc_rb_cMdAry, &grpc_rb_md_ary_data_type,
+ md_ary);
rb_hash_foreach(md_ary_hash, grpc_rb_md_ary_capacity_hash_cb, md_ary_obj);
md_ary->metadata = gpr_malloc(md_ary->capacity * sizeof(grpc_metadata));
rb_hash_foreach(md_ary_hash, grpc_rb_md_ary_fill_hash_cb, md_ary_obj);
@@ -556,7 +589,7 @@ static VALUE grpc_rb_call_run_batch(VALUE self, VALUE cqueue, VALUE tag,
grpc_event *ev = NULL;
grpc_call_error err;
VALUE result = Qnil;
- Data_Get_Struct(self, grpc_call, call);
+ TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
/* Validate the ops args, adding them to a ruby array */
if (TYPE(ops_hash) != T_HASH) {
@@ -736,7 +769,7 @@ void Init_grpc_call() {
/* Gets the call from the ruby object */
grpc_call *grpc_rb_get_wrapped_call(VALUE v) {
grpc_call *c = NULL;
- Data_Get_Struct(v, grpc_call, c);
+ TypedData_Get_Struct(v, grpc_call, &grpc_call_data_type, c);
return c;
}
@@ -753,6 +786,5 @@ VALUE grpc_rb_wrap_call(grpc_call *c) {
rb_hash_aset(hash_all_calls, OFFT2NUM((VALUE)c),
UINT2NUM(NUM2UINT(obj) + 1));
}
- return Data_Wrap_Struct(grpc_rb_cCall, GC_NOT_MARKED,
- grpc_rb_call_destroy, c);
+ return TypedData_Wrap_Struct(grpc_rb_cCall, &grpc_call_data_type, c);
}
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index 9bd7c2edf9..214675af92 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -105,13 +105,19 @@ static void grpc_rb_channel_mark(void *p) {
}
}
+static rb_data_type_t grpc_channel_data_type = {
+ "grpc_channel",
+ {grpc_rb_channel_mark, grpc_rb_channel_free, GRPC_RB_MEMSIZE_UNAVAILABLE},
+ NULL, NULL,
+ RUBY_TYPED_FREE_IMMEDIATELY
+};
+
/* Allocates grpc_rb_channel instances. */
static VALUE grpc_rb_channel_alloc(VALUE cls) {
grpc_rb_channel *wrapper = ALLOC(grpc_rb_channel);
wrapper->wrapped = NULL;
wrapper->mark = Qnil;
- return Data_Wrap_Struct(cls, grpc_rb_channel_mark, grpc_rb_channel_free,
- wrapper);
+ return TypedData_Wrap_Struct(cls, &grpc_channel_data_type, wrapper);
}
/*
@@ -135,7 +141,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
/* "21" == 2 mandatory args, 1 (credentials) is optional */
rb_scan_args(argc, argv, "21", &target, &channel_args, &credentials);
- Data_Get_Struct(self, grpc_rb_channel, wrapper);
+ TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
target_chars = StringValueCStr(target);
grpc_rb_hash_convert_to_channel_args(channel_args, &args);
if (credentials == Qnil) {
@@ -176,8 +182,8 @@ static VALUE grpc_rb_channel_init_copy(VALUE copy, VALUE orig) {
return Qnil;
}
- Data_Get_Struct(orig, grpc_rb_channel, orig_ch);
- Data_Get_Struct(copy, grpc_rb_channel, copy_ch);
+ TypedData_Get_Struct(orig, grpc_rb_channel, &grpc_channel_data_type, orig_ch);
+ TypedData_Get_Struct(copy, grpc_rb_channel, &grpc_channel_data_type, copy_ch);
/* use ruby's MEMCPY to make a byte-for-byte copy of the channel wrapper
* object. */
@@ -198,7 +204,7 @@ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE cqueue, VALUE method,
char *host_chars = StringValueCStr(host);
cq = grpc_rb_get_wrapped_completion_queue(cqueue);
- Data_Get_Struct(self, grpc_rb_channel, wrapper);
+ TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
ch = wrapper->wrapped;
if (ch == NULL) {
rb_raise(rb_eRuntimeError, "closed!");
@@ -231,7 +237,7 @@ static VALUE grpc_rb_channel_destroy(VALUE self) {
grpc_rb_channel *wrapper = NULL;
grpc_channel *ch = NULL;
- Data_Get_Struct(self, grpc_rb_channel, wrapper);
+ TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
ch = wrapper->wrapped;
if (ch != NULL) {
grpc_channel_destroy(ch);
@@ -277,6 +283,6 @@ void Init_grpc_channel() {
/* Gets the wrapped channel from the ruby wrapper */
grpc_channel *grpc_rb_get_wrapped_channel(VALUE v) {
grpc_rb_channel *wrapper = NULL;
- Data_Get_Struct(v, grpc_rb_channel, wrapper);
+ TypedData_Get_Struct(v, grpc_rb_channel, &grpc_channel_data_type, wrapper);
return wrapper->wrapped;
}
diff --git a/src/ruby/ext/grpc/rb_channel_args.c b/src/ruby/ext/grpc/rb_channel_args.c
index 9b92ec1514..acd545f5d2 100644
--- a/src/ruby/ext/grpc/rb_channel_args.c
+++ b/src/ruby/ext/grpc/rb_channel_args.c
@@ -38,6 +38,13 @@
#include "rb_grpc.h"
+static rb_data_type_t grpc_rb_channel_args_data_type = {
+ "grpc_channel_args",
+ {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, GRPC_RB_MEMSIZE_UNAVAILABLE},
+ NULL, NULL,
+ RUBY_TYPED_FREE_IMMEDIATELY
+};
+
/* A callback the processes the hash key values in channel_args hash */
static int grpc_rb_channel_create_in_process_add_args_hash_cb(VALUE key,
VALUE val,
@@ -60,7 +67,8 @@ static int grpc_rb_channel_create_in_process_add_args_hash_cb(VALUE key,
return ST_STOP;
}
- Data_Get_Struct(args_obj, grpc_channel_args, args);
+ TypedData_Get_Struct(args_obj, grpc_channel_args,
+ &grpc_rb_channel_args_data_type, args);
if (args->num_args <= 0) {
rb_raise(rb_eRuntimeError, "hash_cb bug: num_args is %lu for key:%s",
args->num_args, StringValueCStr(key));
@@ -126,8 +134,9 @@ static VALUE grpc_rb_hash_convert_to_channel_args0(VALUE as_value) {
MEMZERO(params->dst->args, grpc_arg, num_args);
rb_hash_foreach(params->src_hash,
grpc_rb_channel_create_in_process_add_args_hash_cb,
- Data_Wrap_Struct(grpc_rb_cChannelArgs, GC_NOT_MARKED,
- GC_DONT_FREE, params->dst));
+ TypedData_Wrap_Struct(grpc_rb_cChannelArgs,
+ &grpc_rb_channel_args_data_type,
+ params->dst));
/* reset num_args as grpc_rb_channel_create_in_process_add_args_hash_cb
* decrements it during has processing */
params->dst->num_args = num_args;
diff --git a/src/ruby/ext/grpc/rb_completion_queue.c b/src/ruby/ext/grpc/rb_completion_queue.c
index a72f01ffb8..3cf6c313ee 100644
--- a/src/ruby/ext/grpc/rb_completion_queue.c
+++ b/src/ruby/ext/grpc/rb_completion_queue.c
@@ -33,7 +33,8 @@
#include "rb_completion_queue.h"
-#include <ruby.h>
+#include <ruby/ruby.h>
+#include <ruby/thread.h>
#include <grpc/grpc.h>
#include <grpc/support/time.h>
@@ -52,14 +53,16 @@ typedef struct next_call_stack {
} next_call_stack;
/* Calls grpc_completion_queue_next without holding the ruby GIL */
-static void *grpc_rb_completion_queue_next_no_gil(next_call_stack *next_call) {
+static void *grpc_rb_completion_queue_next_no_gil(void *param) {
+ next_call_stack *const next_call = (next_call_stack*)param;
next_call->event =
grpc_completion_queue_next(next_call->cq, next_call->timeout);
return NULL;
}
/* Calls grpc_completion_queue_pluck without holding the ruby GIL */
-static void *grpc_rb_completion_queue_pluck_no_gil(next_call_stack *next_call) {
+static void *grpc_rb_completion_queue_pluck_no_gil(void *param) {
+ next_call_stack *const next_call = (next_call_stack*)param;
next_call->event = grpc_completion_queue_pluck(next_call->cq, next_call->tag,
next_call->timeout);
return NULL;
@@ -116,21 +119,31 @@ static void grpc_rb_completion_queue_destroy(void *p) {
grpc_completion_queue_destroy(cq);
}
+static rb_data_type_t grpc_rb_completion_queue_data_type = {
+ "grpc_completion_queue",
+ {GRPC_RB_GC_NOT_MARKED, grpc_rb_completion_queue_destroy,
+ GRPC_RB_MEMSIZE_UNAVAILABLE},
+ NULL, NULL,
+ /* cannot immediately free because grpc_rb_completion_queue_shutdown_drain
+ * calls rb_thread_call_without_gvl. */
+ 0
+};
+
/* Allocates a completion queue. */
static VALUE grpc_rb_completion_queue_alloc(VALUE cls) {
grpc_completion_queue *cq = grpc_completion_queue_create();
if (cq == NULL) {
rb_raise(rb_eArgError, "could not create a completion queue: not sure why");
}
- return Data_Wrap_Struct(cls, GC_NOT_MARKED, grpc_rb_completion_queue_destroy,
- cq);
+ return TypedData_Wrap_Struct(cls, &grpc_rb_completion_queue_data_type, cq);
}
/* Blocks until the next event is available, and returns the event. */
static VALUE grpc_rb_completion_queue_next(VALUE self, VALUE timeout) {
next_call_stack next_call;
MEMZERO(&next_call, next_call_stack, 1);
- Data_Get_Struct(self, grpc_completion_queue, next_call.cq);
+ TypedData_Get_Struct(self, grpc_completion_queue,
+ &grpc_rb_completion_queue_data_type, next_call.cq);
next_call.timeout = grpc_rb_time_timeval(timeout, /* absolute time*/ 0);
next_call.event = NULL;
rb_thread_call_without_gvl(grpc_rb_completion_queue_next_no_gil,
@@ -158,7 +171,8 @@ grpc_event* grpc_rb_completion_queue_pluck_event(VALUE self, VALUE tag,
VALUE timeout) {
next_call_stack next_call;
MEMZERO(&next_call, next_call_stack, 1);
- Data_Get_Struct(self, grpc_completion_queue, next_call.cq);
+ TypedData_Get_Struct(self, grpc_completion_queue,
+ &grpc_rb_completion_queue_data_type, next_call.cq);
next_call.timeout = grpc_rb_time_timeval(timeout, /* absolute time*/ 0);
next_call.tag = ROBJECT(tag);
next_call.event = NULL;
@@ -192,6 +206,7 @@ void Init_grpc_completion_queue() {
/* Gets the wrapped completion queue from the ruby wrapper */
grpc_completion_queue *grpc_rb_get_wrapped_completion_queue(VALUE v) {
grpc_completion_queue *cq = NULL;
- Data_Get_Struct(v, grpc_completion_queue, cq);
+ TypedData_Get_Struct(v, grpc_completion_queue,
+ &grpc_rb_completion_queue_data_type, cq);
return cq;
}
diff --git a/src/ruby/ext/grpc/rb_credentials.c b/src/ruby/ext/grpc/rb_credentials.c
index 122cffc92f..1ec88914e4 100644
--- a/src/ruby/ext/grpc/rb_credentials.c
+++ b/src/ruby/ext/grpc/rb_credentials.c
@@ -86,14 +86,21 @@ static void grpc_rb_credentials_mark(void *p) {
}
}
+static rb_data_type_t grpc_rb_credentials_data_type = {
+ "grpc_credentials",
+ {grpc_rb_credentials_mark, grpc_rb_credentials_free,
+ GRPC_RB_MEMSIZE_UNAVAILABLE},
+ NULL,
+ NULL,
+ RUBY_TYPED_FREE_IMMEDIATELY};
+
/* Allocates Credential instances.
Provides safe initial defaults for the instance fields. */
static VALUE grpc_rb_credentials_alloc(VALUE cls) {
grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials);
wrapper->wrapped = NULL;
wrapper->mark = Qnil;
- return Data_Wrap_Struct(cls, grpc_rb_credentials_mark,
- grpc_rb_credentials_free, wrapper);
+ return TypedData_Wrap_Struct(cls, &grpc_rb_credentials_data_type, wrapper);
}
/* Clones Credentials instances.
@@ -113,8 +120,10 @@ static VALUE grpc_rb_credentials_init_copy(VALUE copy, VALUE orig) {
rb_raise(rb_eTypeError, "not a %s", rb_obj_classname(grpc_rb_cCredentials));
}
- Data_Get_Struct(orig, grpc_rb_credentials, orig_cred);
- Data_Get_Struct(copy, grpc_rb_credentials, copy_cred);
+ TypedData_Get_Struct(orig, grpc_rb_credentials,
+ &grpc_rb_credentials_data_type, orig_cred);
+ TypedData_Get_Struct(copy, grpc_rb_credentials,
+ &grpc_rb_credentials_data_type, copy_cred);
/* use ruby's MEMCPY to make a byte-for-byte copy of the credentials
* wrapper object. */
@@ -136,8 +145,7 @@ static VALUE grpc_rb_default_credentials_create(VALUE cls) {
}
wrapper->mark = Qnil;
- return Data_Wrap_Struct(cls, grpc_rb_credentials_mark,
- grpc_rb_credentials_free, wrapper);
+ return TypedData_Wrap_Struct(cls, &grpc_rb_credentials_data_type, wrapper);
}
/*
@@ -154,8 +162,7 @@ static VALUE grpc_rb_compute_engine_credentials_create(VALUE cls) {
}
wrapper->mark = Qnil;
- return Data_Wrap_Struct(cls, grpc_rb_credentials_mark,
- grpc_rb_credentials_free, wrapper);
+ return TypedData_Wrap_Struct(cls, &grpc_rb_credentials_data_type, wrapper);
}
/*
@@ -169,8 +176,10 @@ static VALUE grpc_rb_composite_credentials_create(VALUE self, VALUE other) {
grpc_rb_credentials *other_wrapper = NULL;
grpc_rb_credentials *wrapper = NULL;
- Data_Get_Struct(self, grpc_rb_credentials, self_wrapper);
- Data_Get_Struct(other, grpc_rb_credentials, other_wrapper);
+ TypedData_Get_Struct(self, grpc_rb_credentials,
+ &grpc_rb_credentials_data_type, self_wrapper);
+ TypedData_Get_Struct(other, grpc_rb_credentials,
+ &grpc_rb_credentials_data_type, other_wrapper);
wrapper = ALLOC(grpc_rb_credentials);
wrapper->wrapped = grpc_composite_credentials_create(self_wrapper->wrapped,
other_wrapper->wrapped);
@@ -181,8 +190,8 @@ static VALUE grpc_rb_composite_credentials_create(VALUE self, VALUE other) {
}
wrapper->mark = Qnil;
- return Data_Wrap_Struct(grpc_rb_cCredentials, grpc_rb_credentials_mark,
- grpc_rb_credentials_free, wrapper);
+ return TypedData_Wrap_Struct(grpc_rb_cCredentials,
+ &grpc_rb_credentials_data_type, wrapper);
}
/* The attribute used on the mark object to hold the pem_root_certs. */
@@ -217,7 +226,8 @@ static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) {
rb_scan_args(argc, argv, "12", &pem_root_certs, &pem_private_key,
&pem_cert_chain);
- Data_Get_Struct(self, grpc_rb_credentials, wrapper);
+ TypedData_Get_Struct(self, grpc_rb_credentials,
+ &grpc_rb_credentials_data_type, wrapper);
if (pem_root_certs == Qnil) {
rb_raise(rb_eRuntimeError,
"could not create a credential: nil pem_root_certs");
@@ -228,8 +238,8 @@ static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) {
} else {
key_cert_pair.private_key = RSTRING_PTR(pem_private_key);
key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain);
- creds = grpc_ssl_credentials_create(
- RSTRING_PTR(pem_root_certs), &key_cert_pair);
+ creds = grpc_ssl_credentials_create(RSTRING_PTR(pem_root_certs),
+ &key_cert_pair);
}
if (creds == NULL) {
rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
@@ -253,8 +263,8 @@ void Init_grpc_credentials() {
rb_define_alloc_func(grpc_rb_cCredentials, grpc_rb_credentials_alloc);
/* Provides a ruby constructor and support for dup/clone. */
- rb_define_method(grpc_rb_cCredentials, "initialize",
- grpc_rb_credentials_init, -1);
+ rb_define_method(grpc_rb_cCredentials, "initialize", grpc_rb_credentials_init,
+ -1);
rb_define_method(grpc_rb_cCredentials, "initialize_copy",
grpc_rb_credentials_init_copy, 1);
@@ -277,6 +287,7 @@ void Init_grpc_credentials() {
/* Gets the wrapped grpc_credentials from the ruby wrapper */
grpc_credentials *grpc_rb_get_wrapped_credentials(VALUE v) {
grpc_rb_credentials *wrapper = NULL;
- Data_Get_Struct(v, grpc_rb_credentials, wrapper);
+ TypedData_Get_Struct(v, grpc_rb_credentials, &grpc_rb_credentials_data_type,
+ wrapper);
return wrapper->wrapped;
}
diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c
index 1cbd1aa8bd..699548b940 100644
--- a/src/ruby/ext/grpc/rb_grpc.c
+++ b/src/ruby/ext/grpc/rb_grpc.c
@@ -34,7 +34,8 @@
#include "rb_grpc.h"
#include <math.h>
-#include <ruby.h>
+#include <ruby/ruby.h>
+#include <ruby/vm.h>
#include <sys/time.h>
#include <grpc/grpc.h>
@@ -46,12 +47,15 @@
#include "rb_credentials.h"
#include "rb_server_credentials.h"
-/* Define common vars and funcs declared in rb.h */
-const RUBY_DATA_FUNC GC_NOT_MARKED = NULL;
-const RUBY_DATA_FUNC GC_DONT_FREE = NULL;
-
static VALUE grpc_rb_cTimeVal = Qnil;
+static rb_data_type_t grpc_rb_timespec_data_type = {
+ "gpr_timespec",
+ {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, GRPC_RB_MEMSIZE_UNAVAILABLE},
+ NULL,
+ NULL,
+ RUBY_TYPED_FREE_IMMEDIATELY};
+
/* Alloc func that blocks allocation of a given object by raising an
* exception. */
VALUE grpc_rb_cannot_alloc(VALUE cls) {
@@ -97,7 +101,8 @@ gpr_timespec grpc_rb_time_timeval(VALUE time, int interval) {
switch (TYPE(time)) {
case T_DATA:
if (CLASS_OF(time) == grpc_rb_cTimeVal) {
- Data_Get_Struct(time, gpr_timespec, time_const);
+ TypedData_Get_Struct(time, gpr_timespec, &grpc_rb_timespec_data_type,
+ time_const);
t = *time_const;
} else if (CLASS_OF(time) == rb_cTime) {
t.tv_sec = NUM2INT(rb_funcall(time, id_tv_sec, 0));
@@ -201,7 +206,8 @@ static ID id_to_s;
/* Converts a wrapped time constant to a standard time. */
static VALUE grpc_rb_time_val_to_time(VALUE self) {
gpr_timespec *time_const = NULL;
- Data_Get_Struct(self, gpr_timespec, time_const);
+ TypedData_Get_Struct(self, gpr_timespec, &grpc_rb_timespec_data_type,
+ time_const);
return rb_funcall(rb_cTime, id_at, 2, INT2NUM(time_const->tv_sec),
INT2NUM(time_const->tv_nsec));
}
@@ -222,18 +228,18 @@ static void Init_grpc_time_consts() {
rb_define_module_under(grpc_rb_mGrpcCore, "TimeConsts");
grpc_rb_cTimeVal =
rb_define_class_under(grpc_rb_mGrpcCore, "TimeSpec", rb_cObject);
- rb_define_const(grpc_rb_mTimeConsts, "ZERO",
- Data_Wrap_Struct(grpc_rb_cTimeVal,
- GC_NOT_MARKED, GC_DONT_FREE,
- (void *)&gpr_time_0));
- rb_define_const(grpc_rb_mTimeConsts, "INFINITE_FUTURE",
- Data_Wrap_Struct(grpc_rb_cTimeVal,
- GC_NOT_MARKED, GC_DONT_FREE,
- (void *)&gpr_inf_future));
- rb_define_const(grpc_rb_mTimeConsts, "INFINITE_PAST",
- Data_Wrap_Struct(grpc_rb_cTimeVal,
- GC_NOT_MARKED, GC_DONT_FREE,
- (void *)&gpr_inf_past));
+ rb_define_const(
+ grpc_rb_mTimeConsts, "ZERO",
+ TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
+ (void *)&gpr_time_0));
+ rb_define_const(
+ grpc_rb_mTimeConsts, "INFINITE_FUTURE",
+ TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
+ (void *)&gpr_inf_future));
+ rb_define_const(
+ grpc_rb_mTimeConsts, "INFINITE_PAST",
+ TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
+ (void *)&gpr_inf_past));
rb_define_method(grpc_rb_cTimeVal, "to_time", grpc_rb_time_val_to_time, 0);
rb_define_method(grpc_rb_cTimeVal, "inspect", grpc_rb_time_val_inspect, 0);
rb_define_method(grpc_rb_cTimeVal, "to_s", grpc_rb_time_val_to_s, 0);
@@ -244,7 +250,7 @@ static void Init_grpc_time_consts() {
id_tv_nsec = rb_intern("tv_nsec");
}
-static void grpc_rb_shutdown(void *vm) { grpc_shutdown(); }
+static void grpc_rb_shutdown(ruby_vm_t *vm) { grpc_shutdown(); }
/* Initialize the GRPC module structs */
diff --git a/src/ruby/ext/grpc/rb_grpc.h b/src/ruby/ext/grpc/rb_grpc.h
index 1d411baf5b..a502273de1 100644
--- a/src/ruby/ext/grpc/rb_grpc.h
+++ b/src/ruby/ext/grpc/rb_grpc.h
@@ -58,12 +58,16 @@ extern VALUE sym_metadata;
/* GC_NOT_MARKED is used in calls to Data_Wrap_Struct to indicate that the
wrapped struct does not need to participate in ruby gc. */
-extern const RUBY_DATA_FUNC GC_NOT_MARKED;
+#define GRPC_RB_GC_NOT_MARKED (RUBY_DATA_FUNC)(NULL)
/* GC_DONT_FREED is used in calls to Data_Wrap_Struct to indicate that the
wrapped struct should not be freed the wrapped ruby object is released by
the garbage collector. */
-extern const RUBY_DATA_FUNC GC_DONT_FREE;
+#define GRPC_RB_GC_DONT_FREE (RUBY_DATA_FUNC)(NULL)
+
+/* GRPC_RB_MEMSIZE_UNAVAILABLE is used in rb_data_type_t to indicate that the
+ * number of bytes used by the wrapped struct is not available. */
+#define GRPC_RB_MEMSIZE_UNAVAILABLE (size_t (*)(const void*))(NULL)
/* A ruby object alloc func that fails by raising an exception. */
VALUE grpc_rb_cannot_alloc(VALUE cls);
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index 80f7760ebb..bc0878af05 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -88,13 +88,23 @@ static void grpc_rb_server_mark(void *p) {
}
}
+static const rb_data_type_t grpc_rb_server_data_type = {
+ "grpc_server",
+ {grpc_rb_server_mark, grpc_rb_server_free, GRPC_RB_MEMSIZE_UNAVAILABLE},
+ NULL,
+ NULL,
+ /* 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};
+
/* Allocates grpc_rb_server instances. */
static VALUE grpc_rb_server_alloc(VALUE cls) {
grpc_rb_server *wrapper = ALLOC(grpc_rb_server);
wrapper->wrapped = NULL;
wrapper->mark = Qnil;
- return Data_Wrap_Struct(cls, grpc_rb_server_mark, grpc_rb_server_free,
- wrapper);
+ return TypedData_Wrap_Struct(cls, &grpc_rb_server_data_type, wrapper);
}
/*
@@ -110,7 +120,8 @@ static VALUE grpc_rb_server_init(VALUE self, VALUE cqueue, VALUE channel_args) {
grpc_channel_args args;
MEMZERO(&args, grpc_channel_args, 1);
cq = grpc_rb_get_wrapped_completion_queue(cqueue);
- Data_Get_Struct(self, grpc_rb_server, wrapper);
+ TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type,
+ wrapper);
grpc_rb_hash_convert_to_channel_args(channel_args, &args);
srv = grpc_server_create(cq, &args);
@@ -146,8 +157,10 @@ static VALUE grpc_rb_server_init_copy(VALUE copy, VALUE orig) {
rb_raise(rb_eTypeError, "not a %s", rb_obj_classname(grpc_rb_cServer));
}
- Data_Get_Struct(orig, grpc_rb_server, orig_srv);
- Data_Get_Struct(copy, grpc_rb_server, copy_srv);
+ TypedData_Get_Struct(orig, grpc_rb_server, &grpc_rb_server_data_type,
+ orig_srv);
+ TypedData_Get_Struct(copy, grpc_rb_server, &grpc_rb_server_data_type,
+ copy_srv);
/* use ruby's MEMCPY to make a byte-for-byte copy of the server wrapper
object. */
@@ -194,7 +207,7 @@ static VALUE grpc_rb_server_request_call(VALUE self, VALUE cqueue,
grpc_call_error err;
request_call_stack st;
VALUE result;
- Data_Get_Struct(self, grpc_rb_server, s);
+ TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
if (s->wrapped == NULL) {
rb_raise(rb_eRuntimeError, "closed!");
return Qnil;
@@ -245,7 +258,7 @@ static VALUE grpc_rb_server_request_call(VALUE self, VALUE cqueue,
static VALUE grpc_rb_server_start(VALUE self) {
grpc_rb_server *s = NULL;
- Data_Get_Struct(self, grpc_rb_server, s);
+ TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
if (s->wrapped == NULL) {
rb_raise(rb_eRuntimeError, "closed!");
} else {
@@ -256,7 +269,7 @@ static VALUE grpc_rb_server_start(VALUE self) {
static VALUE grpc_rb_server_destroy(VALUE self) {
grpc_rb_server *s = NULL;
- Data_Get_Struct(self, grpc_rb_server, s);
+ TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
if (s->wrapped != NULL) {
grpc_server_shutdown(s->wrapped);
grpc_server_destroy(s->wrapped);
@@ -288,7 +301,7 @@ static VALUE grpc_rb_server_add_http2_port(int argc, VALUE *argv, VALUE self) {
/* "11" == 1 mandatory args, 1 (rb_creds) is optional */
rb_scan_args(argc, argv, "11", &port, &rb_creds);
- Data_Get_Struct(self, grpc_rb_server, s);
+ TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
if (s->wrapped == NULL) {
rb_raise(rb_eRuntimeError, "closed!");
return Qnil;
@@ -340,6 +353,6 @@ void Init_grpc_server() {
/* Gets the wrapped server from the ruby wrapper */
grpc_server *grpc_rb_get_wrapped_server(VALUE v) {
grpc_rb_server *wrapper = NULL;
- Data_Get_Struct(v, grpc_rb_server, wrapper);
+ TypedData_Get_Struct(v, grpc_rb_server, &grpc_rb_server_data_type, wrapper);
return wrapper->wrapped;
}
diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c
index 5109b96b5f..a86389445f 100644
--- a/src/ruby/ext/grpc/rb_server_credentials.c
+++ b/src/ruby/ext/grpc/rb_server_credentials.c
@@ -86,6 +86,14 @@ static void grpc_rb_server_credentials_mark(void *p) {
}
}
+static const rb_data_type_t grpc_rb_server_credentials_data_type = {
+ "grpc_server_credentials",
+ {grpc_rb_server_credentials_mark, grpc_rb_server_credentials_free,
+ GRPC_RB_MEMSIZE_UNAVAILABLE},
+ NULL, NULL,
+ RUBY_TYPED_FREE_IMMEDIATELY
+};
+
/* Allocates ServerCredential instances.
Provides safe initial defaults for the instance fields. */
@@ -93,8 +101,8 @@ static VALUE grpc_rb_server_credentials_alloc(VALUE cls) {
grpc_rb_server_credentials *wrapper = ALLOC(grpc_rb_server_credentials);
wrapper->wrapped = NULL;
wrapper->mark = Qnil;
- return Data_Wrap_Struct(cls, grpc_rb_server_credentials_mark,
- grpc_rb_server_credentials_free, wrapper);
+ return TypedData_Wrap_Struct(cls, &grpc_rb_server_credentials_data_type,
+ wrapper);
}
/* Clones ServerCredentials instances.
@@ -116,8 +124,10 @@ static VALUE grpc_rb_server_credentials_init_copy(VALUE copy, VALUE orig) {
rb_obj_classname(grpc_rb_cServerCredentials));
}
- Data_Get_Struct(orig, grpc_rb_server_credentials, orig_ch);
- Data_Get_Struct(copy, grpc_rb_server_credentials, copy_ch);
+ TypedData_Get_Struct(orig, grpc_rb_server_credentials,
+ &grpc_rb_server_credentials_data_type, orig_ch);
+ TypedData_Get_Struct(copy, grpc_rb_server_credentials,
+ &grpc_rb_server_credentials_data_type, copy_ch);
/* use ruby's MEMCPY to make a byte-for-byte copy of the server_credentials
wrapper object. */
@@ -153,7 +163,8 @@ static VALUE grpc_rb_server_credentials_init(VALUE self, VALUE pem_root_certs,
grpc_rb_server_credentials *wrapper = NULL;
grpc_server_credentials *creds = NULL;
grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL};
- Data_Get_Struct(self, grpc_rb_server_credentials, wrapper);
+ TypedData_Get_Struct(self, grpc_rb_server_credentials,
+ &grpc_rb_server_credentials_data_type, wrapper);
if (pem_cert_chain == Qnil) {
rb_raise(rb_eRuntimeError,
"could not create a server credential: nil pem_cert_chain");
@@ -206,6 +217,7 @@ void Init_grpc_server_credentials() {
/* Gets the wrapped grpc_server_credentials from the ruby wrapper */
grpc_server_credentials *grpc_rb_get_wrapped_server_credentials(VALUE v) {
grpc_rb_server_credentials *wrapper = NULL;
- Data_Get_Struct(v, grpc_rb_server_credentials, wrapper);
+ TypedData_Get_Struct(v, grpc_rb_server_credentials,
+ &grpc_rb_server_credentials_data_type, wrapper);
return wrapper->wrapped;
}
diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec
index 12d4ab17f2..ae48213c8f 100755
--- a/src/ruby/grpc.gemspec
+++ b/src/ruby/grpc.gemspec
@@ -13,6 +13,9 @@ Gem::Specification.new do |s|
s.description = 'Send RPCs from Ruby using GRPC'
s.license = 'BSD-3-Clause'
+ s.required_ruby_version = '>= 2.0.0'
+ s.requirements << 'libgrpc ~> 0.6.0 needs to be installed'
+
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- spec/*`.split("\n")
s.executables = `git ls-files -- bin/*.rb`.split("\n").map do |f|
@@ -25,13 +28,12 @@ Gem::Specification.new do |s|
s.add_dependency 'googleauth', '~> 0.4' # reqd for interop tests
s.add_dependency 'logging', '~> 1.8'
s.add_dependency 'minitest', '~> 5.4' # reqd for interop tests
- s.add_dependency 'xray', '~> 1.1'
s.add_development_dependency 'bundler', '~> 1.9'
s.add_development_dependency 'rake', '~> 10.4'
s.add_development_dependency 'rake-compiler', '~> 0.9'
- s.add_development_dependency 'rubocop', '~> 0.30'
s.add_development_dependency 'rspec', '~> 3.2'
+ s.add_development_dependency 'rubocop', '~> 0.30'
s.extensions = %w(ext/grpc/extconf.rb)
end
diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb
index dc7672d359..7b2c04aa22 100644
--- a/src/ruby/lib/grpc/generic/client_stub.rb
+++ b/src/ruby/lib/grpc/generic/client_stub.rb
@@ -28,7 +28,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc/generic/active_call'
-require 'xray/thread_dump_signal_handler'
# GRPC contains the General RPC module.
module GRPC
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index 30a4bf1532..c7c8267fa3 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -31,7 +31,9 @@ require 'grpc/grpc'
require 'grpc/generic/active_call'
require 'grpc/generic/service'
require 'thread'
-require 'xray/thread_dump_signal_handler'
+
+# A global that contains signals the gRPC servers should respond to.
+$grpc_signals = []
# GRPC contains the General RPC module.
module GRPC
@@ -50,6 +52,23 @@ module GRPC
# Default max_waiting_requests size is 20
DEFAULT_MAX_WAITING_REQUESTS = 20
+ # Default poll period is 1s
+ DEFAULT_POLL_PERIOD = 1
+
+ # Signal check period is 0.25s
+ SIGNAL_CHECK_PERIOD = 0.25
+
+ # Sets up a signal handler that adds signals to the signal handling global.
+ #
+ # Signal handlers should do as little as humanly possible.
+ # Here, they just add themselves to $grpc_signals
+ #
+ # RpcServer (and later other parts of gRPC) monitors the signals
+ # $grpc_signals in its own non-signal context.
+ def self.trap_signals
+ %w(INT TERM).each { |sig| trap(sig) { $grpc_signals << sig } }
+ end
+
# Creates a new RpcServer.
#
# The RPC server is configured using keyword arguments.
@@ -79,7 +98,7 @@ module GRPC
# with not available to new requests
def initialize(pool_size:DEFAULT_POOL_SIZE,
max_waiting_requests:DEFAULT_MAX_WAITING_REQUESTS,
- poll_period:INFINITE_FUTURE,
+ poll_period:DEFAULT_POLL_PERIOD,
completion_queue_override:nil,
server_override:nil,
**kw)
@@ -117,6 +136,13 @@ module GRPC
return unless @running
@stopped = true
@pool.stop
+
+ # TODO: uncomment this:
+ #
+ # This segfaults in the c layer, so its commented out for now. Shutdown
+ # still occurs, but the c layer has to do the cleanup.
+ #
+ # @server.close
end
# determines if the server is currently running
@@ -139,7 +165,37 @@ module GRPC
running?
end
- # determines if the server is currently stopped
+ # Runs the server in its own thread, then waits for signal INT or TERM on
+ # the current thread to terminate it.
+ def run_till_terminated
+ self.class.trap_signals
+ t = Thread.new { run }
+ wait_till_running
+ loop do
+ sleep SIGNAL_CHECK_PERIOD
+ break unless handle_signals
+ end
+ stop
+ t.join
+ end
+
+ # Handles the signals in $grpc_signals.
+ #
+ # @return false if the server should exit, true if not.
+ def handle_signals
+ loop do
+ sig = $grpc_signals.shift
+ case sig
+ when 'INT'
+ return false
+ when 'TERM'
+ return false
+ end
+ end
+ true
+ end
+
+ # Determines if the server is currently stopped
def stopped?
@stopped ||= false
end
@@ -265,7 +321,10 @@ module GRPC
# Pool is a simple thread pool for running server requests.
class Pool
- def initialize(size)
+ # Default keep alive period is 1s
+ DEFAULT_KEEP_ALIVE = 1
+
+ def initialize(size, keep_alive: DEFAULT_KEEP_ALIVE)
fail 'pool size must be positive' unless size > 0
@jobs = Queue.new
@size = size
@@ -273,6 +332,7 @@ module GRPC
@stop_mutex = Mutex.new
@stop_cond = ConditionVariable.new
@workers = []
+ @keep_alive = keep_alive
end
# Returns the number of jobs waiting
@@ -325,15 +385,13 @@ module GRPC
@workers.size.times { schedule { throw :exit } }
@stopped = true
- # TODO: allow configuration of the keepalive period
- keep_alive = 5
@stop_mutex.synchronize do
- @stop_cond.wait(@stop_mutex, keep_alive) if @workers.size > 0
+ @stop_cond.wait(@stop_mutex, @keep_alive) if @workers.size > 0
end
# Forcibly shutdown any threads that are still alive.
if @workers.size > 0
- logger.warn("forcibly terminating #{@workers.size} worker(s)")
+ logger.info("forcibly terminating #{@workers.size} worker(s)")
@workers.each do |t|
next unless t.alive?
begin
@@ -344,7 +402,6 @@ module GRPC
end
end
end
-
logger.info('stopped, all workers are shutdown')
end
end
diff --git a/src/ruby/spec/credentials_spec.rb b/src/ruby/spec/credentials_spec.rb
index fc97d11a87..8e72e85d54 100644
--- a/src/ruby/spec/credentials_spec.rb
+++ b/src/ruby/spec/credentials_spec.rb
@@ -61,11 +61,11 @@ describe Credentials do
end
describe '#compose' do
- it 'can be completed OK' do
+ it 'cannot be completed OK with 2 SSL creds' do
certs = load_test_certs
cred1 = Credentials.new(*certs)
cred2 = Credentials.new(*certs)
- expect { cred1.compose(cred2) }.to_not raise_error
+ expect { cred1.compose(cred2) }.to raise_error
end
end
end
diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb
index 193c5f2a03..88c6b44c22 100644
--- a/src/ruby/spec/generic/client_stub_spec.rb
+++ b/src/ruby/spec/generic/client_stub_spec.rb
@@ -28,7 +28,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc'
-require 'xray/thread_dump_signal_handler'
# Notifier is useful high-level synchronization primitive.
class Notifier
diff --git a/src/ruby/spec/generic/rpc_server_pool_spec.rb b/src/ruby/spec/generic/rpc_server_pool_spec.rb
index 8383dc1533..3bbc71b822 100644
--- a/src/ruby/spec/generic/rpc_server_pool_spec.rb
+++ b/src/ruby/spec/generic/rpc_server_pool_spec.rb
@@ -28,7 +28,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc'
-require 'xray/thread_dump_signal_handler'
Pool = GRPC::RpcServer::Pool
diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb
index 1323bacfa6..e091c589f5 100644
--- a/src/ruby/spec/generic/rpc_server_spec.rb
+++ b/src/ruby/spec/generic/rpc_server_spec.rb
@@ -28,7 +28,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc'
-require 'xray/thread_dump_signal_handler'
def load_test_certs
test_root = File.join(File.dirname(File.dirname(__FILE__)), 'testdata')