--- a/src/server/daemon/httplistener.c Sat Dec 03 16:31:08 2022 +0100 +++ b/src/server/daemon/httplistener.c Sat Dec 03 18:00:35 2022 +0100 @@ -420,6 +420,15 @@ return listener; } +void http_listener_destroy(HttpListener *listener) { + log_ereport(LOG_DEBUG, "destroy http listener: %s config: %p", listener->name.ptr, listener->cfg); + + if(listener->shutdown) { + pthread_mutex_destroy(&listener->shutdown_mutex); + pthread_cond_destroy(&listener->shutdown_cond); + } +} + int http_listener_start(HttpListener *listener) { if(listener->running) { return 0; @@ -500,8 +509,24 @@ void http_listener_shutdown_acceptors(HttpListener *listener) { - // + if(pthread_mutex_init(&listener->shutdown_mutex, NULL)) { + log_ereport(LOG_FAILURE, "http_listener_shutdown_acceptors: pthread_mutex_init failed: %s", strerror(errno)); + return; + } + if(pthread_cond_init(&listener->shutdown_cond, NULL)) { + log_ereport(LOG_FAILURE, "http_listener_shutdown_acceptors: pthread_cond_init failed: %s", strerror(errno)); + return; + } + listener->shutdown = TRUE; + log_ereport(LOG_INFORM, "shutdown http listener %s", listener->name.ptr); + + pthread_mutex_lock(&listener->shutdown_mutex); + + // shut down acceptors by connecting to the server socket, to make sure + // accept() returns + // the acceptor will handle this as a normal connection, but this should + // not be a problem for(int i=0;i<listener->nacceptors;i++) { listener->acceptors[i]->exit = TRUE; int client4 = http_listener_connect(listener, FALSE); @@ -519,6 +544,16 @@ close(client6); } } + + // The last acceptor will notify listener_shutdown.cond + // It is not really necessary to wait for acceptors to shut down, + // we do it mostly for nicer log messages. The timeout is there + // for making sure, this function never blocks forever. + struct timespec ts; + ts.tv_sec = time(NULL) + 60; + pthread_cond_timedwait(&listener->shutdown_cond, &listener->shutdown_mutex, &ts); + + pthread_mutex_unlock(&listener->shutdown_mutex); } @@ -540,6 +575,8 @@ { log_ereport(LOG_FAILURE, "Listener %s: acceptor_start: %s acceptor", a->listener->name.ptr, strerror(errno)); cfg_unref(a->listener->cfg); + } else { + (void)pthread_detach(a->tid); } } @@ -554,6 +591,7 @@ HttpListener *listener = acceptor->listener; int server_socket; + uint32_t *acceptors_running = &listener->nacceptors_running; ConnectionAddr ca; struct sockaddr *ca_ptr; @@ -572,6 +610,7 @@ } log_ereport(LOG_DEBUG, "acceptor: %p listener: %p start", acceptor, acceptor->listener); + ws_atomic_inc32(acceptors_running); for (;;) { // accept connections @@ -662,6 +701,16 @@ } } + if(ws_atomic_dec32(acceptors_running) == 0) { + // notify + if(listener->shutdown) { + log_ereport(LOG_DEBUG, "last acceptor shutdown: notify cfgmgr"); + pthread_mutex_lock(&listener->shutdown_mutex); + pthread_cond_signal(&listener->shutdown_cond); + pthread_mutex_unlock(&listener->shutdown_mutex); + } + } + acceptor->running = FALSE; cfg_unref(acceptor->listener->cfg);