1
0
mirror of https://github.com/apache/httpd.git synced 2026-10-23 22:49:01 +03:00

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
This commit is contained in:
Jim Jagielski
2026-10-23 16:05:30 +00:00
parent 6681764e7f
commit 55f5db10ee
2 changed files with 17 additions and 5 deletions

View File

@@ -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]

View File

@@ -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++;