|
|
|
@ -75,18 +75,18 @@ struct grpc_tcp_server { |
|
|
|
|
void *cb_arg; |
|
|
|
|
|
|
|
|
|
gpr_mu mu; |
|
|
|
|
gpr_cv cv; |
|
|
|
|
|
|
|
|
|
/* active port count: how many ports are actually still listening */ |
|
|
|
|
int active_ports; |
|
|
|
|
/* number of iomgr callbacks that have been explicitly scheduled during
|
|
|
|
|
* shutdown */ |
|
|
|
|
int iomgr_callbacks_pending; |
|
|
|
|
|
|
|
|
|
/* all listening ports */ |
|
|
|
|
server_port *ports; |
|
|
|
|
size_t nports; |
|
|
|
|
size_t port_capacity; |
|
|
|
|
|
|
|
|
|
/* shutdown callback */ |
|
|
|
|
void(*shutdown_complete)(void *); |
|
|
|
|
void *shutdown_complete_arg; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/* Public function. Allocates the proper data structures to hold a
|
|
|
|
@ -94,34 +94,41 @@ struct grpc_tcp_server { |
|
|
|
|
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->iomgr_callbacks_pending = 0; |
|
|
|
|
s->cb = NULL; |
|
|
|
|
s->cb_arg = NULL; |
|
|
|
|
s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP); |
|
|
|
|
s->nports = 0; |
|
|
|
|
s->port_capacity = INIT_PORT_CAP; |
|
|
|
|
s->shutdown_complete = NULL; |
|
|
|
|
return s; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void dont_care_about_shutdown_completion(void *arg) {} |
|
|
|
|
|
|
|
|
|
/* Public function. Stops and destroys a grpc_tcp_server. */ |
|
|
|
|
void grpc_tcp_server_destroy(grpc_tcp_server *s, |
|
|
|
|
void (*shutdown_done)(void *shutdown_done_arg), |
|
|
|
|
void *shutdown_done_arg) { |
|
|
|
|
void (*shutdown_complete)(void *shutdown_done_arg), |
|
|
|
|
void *shutdown_complete_arg) { |
|
|
|
|
size_t i; |
|
|
|
|
int immediately_done = 0; |
|
|
|
|
gpr_mu_lock(&s->mu); |
|
|
|
|
|
|
|
|
|
s->shutdown_complete = shutdown_complete |
|
|
|
|
? shutdown_complete |
|
|
|
|
: dont_care_about_shutdown_completion; |
|
|
|
|
s->shutdown_complete_arg = shutdown_complete_arg; |
|
|
|
|
|
|
|
|
|
/* First, shutdown all fd's. This will queue abortion calls for all
|
|
|
|
|
of the pending accepts due to the normal operation mechanism. */ |
|
|
|
|
if (s->active_ports == 0) { |
|
|
|
|
immediately_done = 1; |
|
|
|
|
} |
|
|
|
|
for (i = 0; i < s->nports; i++) { |
|
|
|
|
server_port *sp = &s->ports[i]; |
|
|
|
|
sp->shutting_down = 1; |
|
|
|
|
grpc_winsocket_shutdown(sp->socket); |
|
|
|
|
} |
|
|
|
|
/* This happens asynchronously. Wait while that happens. */ |
|
|
|
|
while (s->active_ports || s->iomgr_callbacks_pending) { |
|
|
|
|
gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future(GPR_CLOCK_REALTIME)); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&s->mu); |
|
|
|
|
|
|
|
|
|
/* Now that the accepts have been aborted, we can destroy the sockets.
|
|
|
|
@ -134,8 +141,8 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s, |
|
|
|
|
gpr_free(s->ports); |
|
|
|
|
gpr_free(s); |
|
|
|
|
|
|
|
|
|
if (shutdown_done) { |
|
|
|
|
shutdown_done(shutdown_done_arg); |
|
|
|
|
if (immediately_done) { |
|
|
|
|
s->shutdown_complete(s->shutdown_complete_arg); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -188,13 +195,19 @@ error: |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void decrement_active_ports_and_notify(server_port *sp) { |
|
|
|
|
void(*notify)(void *) = NULL; |
|
|
|
|
void *notify_arg = NULL; |
|
|
|
|
sp->shutting_down = 0; |
|
|
|
|
gpr_mu_lock(&sp->server->mu); |
|
|
|
|
GPR_ASSERT(sp->server->active_ports > 0); |
|
|
|
|
if (0 == --sp->server->active_ports) { |
|
|
|
|
gpr_cv_broadcast(&sp->server->cv); |
|
|
|
|
notify = sp->server->shutdown_complete; |
|
|
|
|
notify_arg = sp->server->shutdown_complete_arg; |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&sp->server->mu); |
|
|
|
|
if (notify != NULL) { |
|
|
|
|
notify(notify_arg); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* start_accept will reference that for the IOCP notification request. */ |
|
|
|
@ -279,12 +292,6 @@ static void on_accept(void *arg, int from_iocp) { |
|
|
|
|
this is necessary in the read/write case, it's useless for the accept |
|
|
|
|
case. We only need to adjust the pending callback count */ |
|
|
|
|
if (!from_iocp) { |
|
|
|
|
gpr_mu_lock(&sp->server->mu); |
|
|
|
|
GPR_ASSERT(sp->server->iomgr_callbacks_pending > 0); |
|
|
|
|
if (0 == --sp->server->iomgr_callbacks_pending) { |
|
|
|
|
gpr_cv_broadcast(&sp->server->cv); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&sp->server->mu); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|