aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ruby/ext/grpc/rb_grpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ruby/ext/grpc/rb_grpc.c')
-rw-r--r--src/ruby/ext/grpc/rb_grpc.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c
index f065a857db..872aed0cfc 100644
--- a/src/ruby/ext/grpc/rb_grpc.c
+++ b/src/ruby/ext/grpc/rb_grpc.c
@@ -23,9 +23,13 @@
#include <math.h>
#include <ruby/vm.h>
+#include <stdbool.h>
#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <grpc/grpc.h>
+#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include "rb_call.h"
#include "rb_call_credentials.h"
@@ -255,7 +259,26 @@ static void Init_grpc_time_consts() {
id_tv_nsec = rb_intern("tv_nsec");
}
-static void grpc_rb_shutdown(void) { grpc_shutdown(); }
+#if GPR_WINDOWS
+static void grpc_ruby_set_init_pid(void) {}
+static bool grpc_ruby_forked_after_init(void) { return false; }
+#else
+static pid_t grpc_init_pid;
+
+static void grpc_ruby_set_init_pid(void) {
+ GPR_ASSERT(grpc_init_pid == 0);
+ grpc_init_pid = getpid();
+}
+
+static bool grpc_ruby_forked_after_init(void) {
+ GPR_ASSERT(grpc_init_pid != 0);
+ return grpc_init_pid != getpid();
+}
+#endif
+
+static void grpc_rb_shutdown(void) {
+ if (!grpc_ruby_forked_after_init()) grpc_shutdown();
+}
/* Initialize the GRPC module structs */
@@ -276,10 +299,17 @@ VALUE sym_metadata = Qundef;
static gpr_once g_once_init = GPR_ONCE_INIT;
static void grpc_ruby_once_init_internal() {
+ grpc_ruby_set_init_pid();
grpc_init();
atexit(grpc_rb_shutdown);
}
+void grpc_ruby_fork_guard() {
+ if (grpc_ruby_forked_after_init()) {
+ rb_raise(rb_eRuntimeError, "grpc cannot be used before and after forking");
+ }
+}
+
static VALUE bg_thread_init_rb_mu = Qundef;
static int bg_thread_init_done = 0;