Make tcp server shutdown non-blocking (as it should be)
diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c
index bb53865..002756f 100644
--- a/src/core/iomgr/tcp_server_posix.c
+++ b/src/core/iomgr/tcp_server_posix.c
@@ -99,13 +99,14 @@
void *cb_arg;
gpr_mu mu;
- gpr_cv cv;
/* active port count: how many ports are actually still listening */
size_t active_ports;
/* destroyed port count: how many ports are completely destroyed */
size_t destroyed_ports;
+ int shutdown;
+
/* all listening ports */
server_port *ports;
size_t nports;
@@ -122,9 +123,9 @@
grpc_tcp_server *grpc_tcp_server_create(void) {
grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
gpr_mu_init(&s->mu);
- gpr_cv_init(&s->cv);
s->active_ports = 0;
s->destroyed_ports = 0;
+ s->shutdown = 0;
s->cb = NULL;
s->cb_arg = NULL;
s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
@@ -137,7 +138,6 @@
s->shutdown_complete(s->shutdown_complete_arg);
gpr_mu_destroy(&s->mu);
- gpr_cv_destroy(&s->cv);
gpr_free(s->ports);
gpr_free(s);
@@ -157,28 +157,17 @@
static void dont_care_about_shutdown_completion(void *ignored) {}
-void grpc_tcp_server_destroy(
- grpc_tcp_server *s, void (*shutdown_complete)(void *shutdown_complete_arg),
- void *shutdown_complete_arg) {
+static void deactivated_all_ports(grpc_tcp_server *s) {
size_t i;
- gpr_mu_lock(&s->mu);
-
- s->shutdown_complete = shutdown_complete
- ? shutdown_complete
- : dont_care_about_shutdown_completion;
- s->shutdown_complete_arg = shutdown_complete_arg;
-
- /* shutdown all fd's */
- for (i = 0; i < s->nports; i++) {
- grpc_fd_shutdown(s->ports[i].emfd);
- }
- /* wait while that happens */
- /* TODO(ctiller): make this asynchronous also */
- while (s->active_ports) {
- gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future);
- }
/* delete ALL the things */
+ gpr_mu_lock(&s->mu);
+
+ if (!s->shutdown) {
+ gpr_mu_unlock(&s->mu);
+ return;
+ }
+
if (s->nports) {
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
@@ -194,6 +183,32 @@
}
}
+void grpc_tcp_server_destroy(
+ grpc_tcp_server *s, void (*shutdown_complete)(void *shutdown_complete_arg),
+ void *shutdown_complete_arg) {
+ size_t i;
+ gpr_mu_lock(&s->mu);
+
+ GPR_ASSERT(!s->shutdown);
+ s->shutdown = 1;
+
+ s->shutdown_complete = shutdown_complete
+ ? shutdown_complete
+ : dont_care_about_shutdown_completion;
+ s->shutdown_complete_arg = shutdown_complete_arg;
+
+ /* shutdown all fd's */
+ if (s->active_ports) {
+ for (i = 0; i < s->nports; i++) {
+ grpc_fd_shutdown(s->ports[i].emfd);
+ }
+ gpr_mu_unlock(&s->mu);
+ } else {
+ gpr_mu_unlock(&s->mu);
+ deactivated_all_ports(s);
+ }
+}
+
/* get max listen queue size on linux */
static void init_max_accept_queue_size(void) {
int n = SOMAXCONN;
@@ -321,9 +336,11 @@
error:
gpr_mu_lock(&sp->server->mu);
if (0 == --sp->server->active_ports) {
- gpr_cv_broadcast(&sp->server->cv);
+ gpr_mu_unlock(&sp->server->mu);
+ deactivated_all_ports(sp->server);
+ } else {
+ gpr_mu_unlock(&sp->server->mu);
}
- gpr_mu_unlock(&sp->server->mu);
}
static int add_socket_to_server(grpc_tcp_server *s, int fd,