From: Yann Ylavic Date: Tue, 25 Nov 2025 11:39:28 +0000 (+0000) Subject: mod_proxy_hcheck: Fix healthcheck disabled due to child restart while updating X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e0e27574e57baf47bad2ce59d258d39256c1c81c;p=thirdparty%2Fapache%2Fhttpd.git mod_proxy_hcheck: Fix healthcheck disabled due to child restart while updating When a child gets restarted while the healthcheck watchdog running for a worker, the healcheck will be disabled for that worker indefinitively because its ->updated time remains zero. Fix all zero ->updated time at startup. * mod_proxy_hcheck.c(hc_watchdog_callback): Have AP_WATCHDOG_STATE_STARTING set the ->updated time of all the workers to "now" (if zero). Move up scoped variables common to AP_WATCHDOG_STATE_{STARTING,RUNNING} loops. Reported by: Lubos Uhliarik git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1929972 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/proxy/mod_proxy_hcheck.c b/modules/proxy/mod_proxy_hcheck.c index 568603594d..92e1bced28 100644 --- a/modules/proxy/mod_proxy_hcheck.c +++ b/modules/proxy/mod_proxy_hcheck.c @@ -989,12 +989,32 @@ static apr_status_t hc_watchdog_callback(int state, void *data, sctx_t *ctx = (sctx_t *)data; server_rec *s = ctx->s; proxy_server_conf *conf; + proxy_worker **workers; + proxy_worker *worker; + apr_time_t now; + int i, n; + + conf = ap_get_module_config(s->module_config, &proxy_module); switch (state) { case AP_WATCHDOG_STATE_STARTING: ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(03258) "%s watchdog started.", HCHECK_WATHCHDOG_NAME); + /* If a child exits while running an hcheck the ->updated time will + * be zero, preventing further hcheck for the worker. + */ + now = apr_time_now(); + balancer = (proxy_balancer *)conf->balancers->elts; + for (i = 0; i < conf->balancers->nelts; i++, balancer++) { + workers = (proxy_worker **)balancer->workers->elts; + for (n = 0; n < balancer->workers->nelts; n++, workers++) { + worker = *workers; + if (worker->s->updated == 0) { + worker->s->updated = now; + } + } + } #if HC_USE_THREADS if (tpsize && hctp == NULL) { rv = apr_thread_pool_create(&hctp, tpsize, @@ -1020,29 +1040,28 @@ static apr_status_t hc_watchdog_callback(int state, void *data, case AP_WATCHDOG_STATE_RUNNING: /* loop thru all workers */ - if (s) { - int i; - conf = (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module); + { balancer = (proxy_balancer *)conf->balancers->elts; - ctx->s = s; for (i = 0; i < conf->balancers->nelts; i++, balancer++) { - int n; - apr_time_t now; - proxy_worker **workers; - proxy_worker *worker; /* Have any new balancers or workers been added dynamically? */ ap_proxy_sync_balancer(balancer, s, conf); - workers = (proxy_worker **)balancer->workers->elts; + now = apr_time_now(); - for (n = 0; n < balancer->workers->nelts; n++) { + workers = (proxy_worker **)balancer->workers->elts; + for (n = 0; n < balancer->workers->nelts; n++, workers++) { worker = *workers; if (!PROXY_WORKER_IS(worker, PROXY_WORKER_STOPPED) && (worker->s->method != NONE) && - (worker->s->updated != 0) && - (now > worker->s->updated + worker->s->interval)) { + (now > worker->s->updated + worker->s->interval) && + (worker->s->updated != 0)) { baton_t *baton; apr_pool_t *ptemp; + /* Zero to prevent concurrent checks for the same worker, + * should a check take longer than the watchdog interval. + */ + worker->s->updated = 0; + ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s, "Checking %s worker: %s [%d] (%pp)", balancer->s->name, worker->s->name, worker->s->method, worker); @@ -1060,7 +1079,7 @@ static apr_status_t hc_watchdog_callback(int state, void *data, apr_pool_destroy(ptemp); return rv; } - worker->s->updated = 0; + #if HC_USE_THREADS if (hctp) { apr_thread_pool_push(hctp, hc_check, (void *)baton, @@ -1074,7 +1093,6 @@ static apr_status_t hc_watchdog_callback(int state, void *data, hc_check(NULL, baton); } } - workers++; } } }