From 55f5db10eed42790fca87df880ded1b9f41cd938 Mon Sep 17 00:00:00 2001 From: Jim Jagielski Date: Fri, 23 Oct 2026 16:05:30 +0000 Subject: [PATCH] mod_proxy: update the shared worker status atomically in ap_proxy_set_wstatus() git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1939352 13f79535-47bb-0310-9956-ffa450edef68 --- changes-entries/proxy-set-wstatus-atomic.txt | 4 ++++ modules/proxy/proxy_util.c | 18 +++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 changes-entries/proxy-set-wstatus-atomic.txt diff --git a/changes-entries/proxy-set-wstatus-atomic.txt b/changes-entries/proxy-set-wstatus-atomic.txt new file mode 100644 index 0000000000..2f2b23434a --- /dev/null +++ b/changes-entries/proxy-set-wstatus-atomic.txt @@ -0,0 +1,4 @@ + *) mod_proxy: Update the shared worker status atomically in + ap_proxy_set_wstatus(), so that the balancer-manager, health checks and + mod_proxy_beacon changing different bits at the same time cannot undo + each other's change. [Jim Jagielski] diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index a455226c26..c3ce45c6a4 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -4387,15 +4387,23 @@ ap_proxy_hashfunc(const char *str, proxy_hash_t method) PROXY_DECLARE(apr_status_t) ap_proxy_set_wstatus(char c, int set, proxy_worker *w) { - unsigned int *status = &w->s->status; + volatile apr_uint32_t *status = (volatile apr_uint32_t *)&w->s->status; char flag = toupper(c); proxy_wstat_t *pwt = proxy_wstat_tbl; while (pwt->bit) { if (flag == pwt->flag) { - if (set) - *status |= pwt->bit; - else - *status &= ~(pwt->bit); + /* + * The status word is shared by every process and thread, and is + * changed from several places at once (balancer-manager, health + * checks, mod_proxy_beacon, ...), each setting only its own bit. + * A plain |= / &= can lose another one's change in between its + * read and its write. + */ + apr_uint32_t old, upd; + do { + old = *status; + upd = set ? (old | pwt->bit) : (old & ~(apr_uint32_t)pwt->bit); + } while (apr_atomic_cas32(status, upd, old) != old); return APR_SUCCESS; } pwt++;