aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ruby
diff options
context:
space:
mode:
authorGravatar Alexander Polcyn <apolcyn@google.com>2016-11-23 10:36:08 -0800
committerGravatar Alexander Polcyn <apolcyn@google.com>2016-11-23 10:36:08 -0800
commit7f8a628f6ae1c67020c9137ea53d2f9f20b00a50 (patch)
tree5bc46a644eefd238a0e54fb88e6682910ce8468e /src/ruby
parent3d48cf4ed30032d417c3b64df11b7fb45220388c (diff)
fix race between app and GC on ruby server shutdown
Diffstat (limited to 'src/ruby')
-rw-r--r--src/ruby/ext/grpc/rb_server.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index bf26841fd2..6783fd3f88 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -37,6 +37,7 @@
#include "rb_server.h"
#include <grpc/grpc.h>
+#include <grpc/support/atm.h>
#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#include "rb_call.h"
@@ -59,11 +60,13 @@ typedef struct grpc_rb_server {
/* The actual server */
grpc_server *wrapped;
grpc_completion_queue *queue;
+ gpr_atm shutdown_started;
} grpc_rb_server;
static void destroy_server(grpc_rb_server *server, gpr_timespec deadline) {
grpc_event ev;
- if (server->wrapped != NULL) {
+ // This can be started by app or implicitly by GC. Avoid a race between these.
+ if (gpr_atm_full_fetch_add(&server->shutdown_started, (gpr_atm)1) == 0) {
grpc_server_shutdown_and_notify(server->wrapped, server->queue, NULL);
ev = rb_completion_queue_pluck(server->queue, NULL, deadline, NULL);
if (ev.type == GRPC_QUEUE_TIMEOUT) {
@@ -115,6 +118,7 @@ static const rb_data_type_t grpc_rb_server_data_type = {
static VALUE grpc_rb_server_alloc(VALUE cls) {
grpc_rb_server *wrapper = ALLOC(grpc_rb_server);
wrapper->wrapped = NULL;
+ wrapper->shutdown_started = (gpr_atm)0;
return TypedData_Wrap_Struct(cls, &grpc_rb_server_data_type, wrapper);
}