aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/surface
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2017-04-12 08:06:44 -0700
committerGravatar Craig Tiller <ctiller@google.com>2017-04-12 08:06:44 -0700
commitbd3cc405290c8f4d4e1ea42b15652e172b34410f (patch)
treee817673e17c9dd12c0d2f04d874d5479d59aadbc /src/core/lib/surface
parent9d9313cfc650e79b44f95d9b7fd9e75e2dc38111 (diff)
Add synchronization so startup completes before shutdown begins
Diffstat (limited to 'src/core/lib/surface')
-rw-r--r--src/core/lib/surface/server.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index 6ac3181482..da4dd703d5 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -212,6 +212,11 @@ struct grpc_server {
gpr_mu mu_global; /* mutex for server and channel state */
gpr_mu mu_call; /* mutex for call-specific state */
+ /* startup synchronization: flag is protected by mu_global, signals whether
+ we are doing the listener start routine or not */
+ bool starting;
+ gpr_cv starting_cv;
+
registered_method *registered_methods;
/** one request matcher for unregistered methods */
request_matcher unregistered_request_matcher;
@@ -389,6 +394,7 @@ static void server_delete(grpc_exec_ctx *exec_ctx, grpc_server *server) {
grpc_channel_args_destroy(exec_ctx, server->channel_args);
gpr_mu_destroy(&server->mu_global);
gpr_mu_destroy(&server->mu_call);
+ gpr_cv_destroy(&server->starting_cv);
while ((rm = server->registered_methods) != NULL) {
server->registered_methods = rm->next;
if (server->started) {
@@ -1022,6 +1028,7 @@ grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) {
gpr_mu_init(&server->mu_global);
gpr_mu_init(&server->mu_call);
+ gpr_cv_init(&server->starting_cv);
/* decremented by grpc_server_destroy */
gpr_ref_init(&server->internal_refcount, 1);
@@ -1084,6 +1091,12 @@ static void start_listeners(grpc_exec_ctx *exec_ctx, void *s,
for (listener *l = server->listeners; l; l = l->next) {
l->start(exec_ctx, server, l->arg, server->pollsets, server->pollset_count);
}
+
+ gpr_mu_lock(&server->mu_global);
+ server->starting = false;
+ gpr_cv_signal(&server->starting_cv);
+ gpr_mu_unlock(&server->mu_global);
+
server_unref(exec_ctx, server);
}
@@ -1122,6 +1135,7 @@ void grpc_server_start(grpc_server *server) {
}
server_ref(server);
+ server->starting = true;
grpc_closure_sched(&exec_ctx, grpc_closure_create(start_listeners, server,
grpc_executor_scheduler),
GRPC_ERROR_NONE);
@@ -1258,8 +1272,14 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
GRPC_API_TRACE("grpc_server_shutdown_and_notify(server=%p, cq=%p, tag=%p)", 3,
(server, cq, tag));
- /* lock, and gather up some stuff to do */
+ /* wait for startup to be finished: locks mu_global */
gpr_mu_lock(&server->mu_global);
+ while (server->starting) {
+ gpr_cv_wait(&server->starting_cv, &server->mu_global,
+ gpr_inf_future(GPR_CLOCK_REALTIME));
+ }
+
+ /* stay locked, and gather up some stuff to do */
grpc_cq_begin_op(cq, tag);
if (server->shutdown_published) {
grpc_cq_end_op(&exec_ctx, cq, tag, GRPC_ERROR_NONE, done_published_shutdown,