@ -137,6 +137,7 @@ struct grpc_server {
size_t cq_count ;
gpr_mu mu ;
gpr_cv cv ;
registered_method * registered_methods ;
requested_call_array requested_calls ;
@ -149,6 +150,7 @@ struct grpc_server {
channel_data root_channel_data ;
listener * listeners ;
int listeners_destroyed ;
gpr_refcount internal_refcount ;
} ;
@ -263,6 +265,7 @@ static void server_unref(grpc_server *server) {
if ( gpr_unref ( & server - > internal_refcount ) ) {
grpc_channel_args_destroy ( server - > channel_args ) ;
gpr_mu_destroy ( & server - > mu ) ;
gpr_cv_destroy ( & server - > cv ) ;
gpr_free ( server - > channel_filters ) ;
requested_call_array_destroy ( & server - > requested_calls ) ;
while ( ( rm = server - > registered_methods ) ! = NULL ) {
@ -620,6 +623,7 @@ grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq,
if ( cq ) addcq ( server , cq ) ;
gpr_mu_init ( & server - > mu ) ;
gpr_cv_init ( & server - > cv ) ;
server - > unregistered_cq = cq ;
/* decremented by grpc_server_destroy */
@ -781,6 +785,15 @@ grpc_transport_setup_result grpc_server_setup_transport(
return result ;
}
static int num_listeners ( grpc_server * server ) {
listener * l ;
int n = 0 ;
for ( l = server - > listeners ; l ; l = l - > next ) {
n + + ;
}
return n ;
}
static void shutdown_internal ( grpc_server * server , gpr_uint8 have_shutdown_tag ,
void * shutdown_tag ) {
listener * l ;
@ -878,11 +891,6 @@ static void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag,
for ( l = server - > listeners ; l ; l = l - > next ) {
l - > destroy ( server , l - > arg ) ;
}
while ( server - > listeners ) {
l = server - > listeners ;
server - > listeners = l - > next ;
gpr_free ( l ) ;
}
}
void grpc_server_shutdown ( grpc_server * server ) {
@ -893,8 +901,18 @@ void grpc_server_shutdown_and_notify(grpc_server *server, void *tag) {
shutdown_internal ( server , 1 , tag ) ;
}
void grpc_server_listener_destroy_done ( void * s ) {
grpc_server * server = s ;
gpr_mu_lock ( & server - > mu ) ;
server - > listeners_destroyed + + ;
gpr_cv_signal ( & server - > cv ) ;
gpr_mu_unlock ( & server - > mu ) ;
}
void grpc_server_destroy ( grpc_server * server ) {
channel_data * c ;
listener * l ;
size_t i ;
gpr_mu_lock ( & server - > mu ) ;
if ( ! server - > shutdown ) {
gpr_mu_unlock ( & server - > mu ) ;
@ -902,6 +920,22 @@ void grpc_server_destroy(grpc_server *server) {
gpr_mu_lock ( & server - > mu ) ;
}
while ( server - > listeners_destroyed ! = num_listeners ( server ) ) {
for ( i = 0 ; i < server - > cq_count ; i + + ) {
gpr_mu_unlock ( & server - > mu ) ;
grpc_cq_hack_spin_pollset ( server - > cqs [ i ] ) ;
gpr_mu_lock ( & server - > mu ) ;
}
gpr_cv_wait ( & server - > cv , & server - > mu , gpr_time_add ( gpr_now ( ) , gpr_time_from_millis ( 100 ) ) ) ;
}
while ( server - > listeners ) {
l = server - > listeners ;
server - > listeners = l - > next ;
gpr_free ( l ) ;
}
for ( c = server - > root_channel_data . next ; c ! = & server - > root_channel_data ;
c = c - > next ) {
shutdown_channel ( c ) ;