diff options
author | Alexander Polcyn <apolcyn@google.com> | 2016-11-23 10:36:08 -0800 |
---|---|---|
committer | Alexander Polcyn <apolcyn@google.com> | 2016-11-23 10:36:08 -0800 |
commit | 7f8a628f6ae1c67020c9137ea53d2f9f20b00a50 (patch) | |
tree | 5bc46a644eefd238a0e54fb88e6682910ce8468e /src/ruby | |
parent | 3d48cf4ed30032d417c3b64df11b7fb45220388c (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.c | 6 |
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); } |