aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ruby/ext
diff options
context:
space:
mode:
Diffstat (limited to 'src/ruby/ext')
-rw-r--r--src/ruby/ext/grpc/rb_grpc.c37
1 files changed, 19 insertions, 18 deletions
diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c
index eefdb93d67..0f9b18fa21 100644
--- a/src/ruby/ext/grpc/rb_grpc.c
+++ b/src/ruby/ext/grpc/rb_grpc.c
@@ -269,20 +269,9 @@ 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;
+static void grpc_rb_shutdown(void) {
grpc_shutdown();
}
-#endif
/* Initialize the GRPC module structs */
@@ -300,18 +289,30 @@ VALUE sym_code = Qundef;
VALUE sym_details = Qundef;
VALUE sym_metadata = Qundef;
+static gpr_once g_once_init = GPR_ONCE_INIT;
+
+static void grpc_ruby_once_init() {
+ grpc_init();
+ atexit(grpc_rb_shutdown);
+}
+
void Init_grpc_c() {
if (!grpc_rb_load_core()) {
rb_raise(rb_eLoadError, "Couldn't find or load gRPC's dynamic C core");
return;
}
- 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
+ /* ruby_vm_at_exit doesn't seem to be working. It would crash once every
+ * blue moon, and some users are getting it repeatedly. See the discussions
+ * - https://github.com/grpc/grpc/pull/5337
+ * - https://bugs.ruby-lang.org/issues/12095
+ *
+ * In order to still be able to handle the (unlikely) situation where the
+ * extension is loaded by a first Ruby VM that is subsequently destroyed,
+ * then loaded again by another VM within the same process, we need to
+ * schedule our initialization and destruction only once.
+ */
+ gpr_once_init(&g_once_init, grpc_ruby_once_init);
grpc_rb_mGRPC = rb_define_module("GRPC");
grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core");