diff --git a/src/core/support/sync.c b/src/core/support/sync.c index ccfe1e25f45..856b5adb862 100644 --- a/src/core/support/sync.c +++ b/src/core/support/sync.c @@ -118,7 +118,9 @@ void gpr_refn(gpr_refcount *r, int n) { } int gpr_unref(gpr_refcount *r) { - return gpr_atm_full_fetch_add(&r->count, -1) == 1; + gpr_atm prior = gpr_atm_full_fetch_add(&r->count, -1); + GPR_ASSERT(prior > 0); + return prior == 1; } void gpr_stats_init(gpr_stats_counter *c, gpr_intptr n) { diff --git a/src/core/surface/server.c b/src/core/surface/server.c index b44cd112f3f..b1e3ec9876f 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -144,6 +144,7 @@ struct grpc_server { requested_call_array requested_calls; gpr_uint8 shutdown; + gpr_uint8 shutdown_published; size_t num_shutdown_tags; shutdown_tag *shutdown_tags; @@ -389,7 +390,8 @@ static int num_listeners(grpc_server *server) { static void maybe_finish_shutdown(grpc_server *server) { size_t i; - if (server->shutdown && server->lists[ALL_CALLS] == NULL && server->listeners_destroyed == num_listeners(server)) { + if (server->shutdown && !server->shutdown_published && server->lists[ALL_CALLS] == NULL && server->listeners_destroyed == num_listeners(server)) { + server->shutdown_published = 1; for (i = 0; i < server->num_shutdown_tags; i++) { grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag, NULL, 1); @@ -456,8 +458,9 @@ static void server_on_recv(void *ptr, int success) { calld->state = ZOMBIED; grpc_iomgr_add_callback(kill_zombie, elem); } - call_list_remove(calld, ALL_CALLS); - maybe_finish_shutdown(chand->server); + if (call_list_remove(calld, ALL_CALLS)) { + maybe_finish_shutdown(chand->server); + } gpr_mu_unlock(&chand->server->mu); break; } @@ -822,9 +825,7 @@ void grpc_server_shutdown_and_notify(grpc_server *server, /* lock, and gather up some stuff to do */ gpr_mu_lock(&server->mu); - for (i = 0; i < server->cq_count; i++) { - grpc_cq_begin_op(server->cqs[i], NULL); - } + grpc_cq_begin_op(cq, NULL); server->shutdown_tags = gpr_realloc(server->shutdown_tags, sizeof(void *) * (server->num_shutdown_tags + 1)); diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index bcd631963fa..a0670a07ccc 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -221,6 +221,9 @@ Server::~Server() { Shutdown(); } } + void* got_tag; + bool ok; + GPR_ASSERT(!cq_.Next(&got_tag, &ok)); grpc_server_destroy(server_); if (thread_pool_owned_) { delete thread_pool_;