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:
4
changes-entries/proxy-set-wstatus-atomic.txt
Normal file
4
changes-entries/proxy-set-wstatus-atomic.txt
Normal 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]
|
||||
@@ -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++;
|
||||
|
||||
Reference in New Issue
Block a user