On 9/11/23 3:50 PM, jfcl...@apache.org wrote:
> Author: jfclere
> Date: Mon Sep 11 13:50:21 2023
> New Revision: 1912245
> 
> URL: http://svn.apache.org/viewvc?rev=1912245&view=rev
> Log:
> Arrange the bybusyness logic and prevent bad busy values
> this closes #383
> 
> Modified:
>     httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_bybusyness.c
>     httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c
>     httpd/httpd/trunk/modules/proxy/proxy_util.c
>     httpd/httpd/trunk/modules/proxy/proxy_util.h
> 

> Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c
> URL: 
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c?rev=1912245&r1=1912244&r2=1912245&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c (original)
> +++ httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c Mon Sep 11 13:50:21 
> 2023
> @@ -17,6 +17,7 @@
>  /* Load balancer module for Apache proxy */
>  
>  #include "mod_proxy.h"
> +#include "proxy_util.h"
>  #include "scoreboard.h"
>  #include "ap_mpm.h"
>  #include "apr_version.h"
> @@ -486,17 +487,6 @@ static void force_recovery(proxy_balance
>      }
>  }
>  
> -static apr_status_t decrement_busy_count(void *worker_)
> -{
> -    proxy_worker *worker = worker_;
> -    
> -    if (worker->s->busy) {
> -        worker->s->busy--;
> -    }
> -
> -    return APR_SUCCESS;
> -}
> -
>  static int proxy_balancer_pre_request(proxy_worker **worker,
>                                        proxy_balancer **balancer,
>                                        request_rec *r,
> @@ -635,7 +625,7 @@ static int proxy_balancer_pre_request(pr
>          *worker = runtime;
>      }
>  
> -    (*worker)->s->busy++;
> +    increment_busy_count(*worker);
>      apr_pool_cleanup_register(r->pool, *worker, decrement_busy_count,
>                                apr_pool_cleanup_null);
>  
> @@ -1575,7 +1565,7 @@ static void balancer_display_page(reques
>                            "</httpd:redirect>\n", NULL);
>                  ap_rprintf(r,
>                             "          <httpd:busy>%" APR_SIZE_T_FMT 
> "</httpd:busy>\n",
> -                           worker->s->busy);
> +                           getbusy_count(worker));
>                  ap_rprintf(r, "          <httpd:lbset>%d</httpd:lbset>\n",
>                             worker->s->lbset);
>                  /* End proxy_worker_stat */
> @@ -1748,7 +1738,7 @@ static void balancer_display_page(reques
>                  ap_rvputs(r, ap_proxy_parse_wstatus(r->pool, worker), NULL);
>                  ap_rputs("</td>", r);
>                  ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td>", 
> worker->s->elected);
> -                ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td>", 
> worker->s->busy);
> +                ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td>", 
> getbusy_count(worker));
>                  ap_rprintf(r, "<td>%d</td><td>", worker->s->lbstatus);
>                  ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r);
>                  ap_rputs("</td><td>", r);
> 
> Modified: httpd/httpd/trunk/modules/proxy/proxy_util.c
> URL: 
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/proxy_util.c?rev=1912245&r1=1912244&r2=1912245&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/modules/proxy/proxy_util.c (original)
> +++ httpd/httpd/trunk/modules/proxy/proxy_util.c Mon Sep 11 13:50:21 2023
> @@ -21,6 +21,7 @@
>  #include "apr_version.h"
>  #include "apr_strings.h"
>  #include "apr_hash.h"
> +#include "apr_atomic.h"
>  #include "http_core.h"
>  #include "proxy_util.h"
>  #include "ajp.h"
> @@ -4984,6 +4985,124 @@ PROXY_DECLARE(apr_status_t) ap_proxy_tun
>      return APR_SUCCESS;
>  }
>  
> +PROXY_DECLARE(apr_status_t) decrement_busy_count(void *worker_)

Why can't we use the respective apr_atomic_sub/add/inc/dec* functions here
instead of the logic below?

> +{
> +    apr_size_t val;
> +    proxy_worker *worker = worker_;
> +
> +#if APR_SIZEOF_VOIDP == 4
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint32_t));
> +    val = apr_atomic_read32(&worker->s->busy);
> +    while (val > 0) {
> +        apr_size_t old = val;
> +        val = apr_atomic_cas32(&worker->s->busy, val - 1, old);
> +        if (val == old) {
> +            break;
> +        }
> +    }
> +#elif APR_VERSION_AT_LEAST(1,7,4) /* APR 64bit atomics not safe before 1.7.4 
> */
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint64_t));
> +    val = apr_atomic_read64(&worker->s->busy);
> +    while (val > 0) {
> +        apr_size_t old = val;
> +        val = apr_atomic_cas64(&worker->s->busy, val - 1, old);
> +        if (val == old) {
> +            break;
> +        }
> +    }
> +#else /* Use atomics for (64bit) pointers */
> +    void *volatile *busy_p = (void *)&worker->s->busy;
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(void*));
> +    AP_DEBUG_ASSERT((apr_uintptr_t)busy_p % sizeof(void*) == 0);
> +    val = (apr_uintptr_t)apr_atomic_casptr((void *)busy_p, NULL, NULL);
> +    while (val > 0) {
> +        apr_size_t old = val;
> +        val = (apr_uintptr_t)apr_atomic_casptr((void *)busy_p,
> +                                               (void *)(apr_uintptr_t)(val - 
> 1),
> +                                               (void *)(apr_uintptr_t)old);
> +        if (val == old) {
> +            break;
> +        }
> +    }
> +#endif
> +    return APR_SUCCESS;
> +}
> +
> +PROXY_DECLARE(void) increment_busy_count(proxy_worker *worker)
> +{
> +    apr_size_t val;
> +#if APR_SIZEOF_VOIDP == 4
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint32_t));
> +    val = apr_atomic_read32(&worker->s->busy);
> +    while (val < APR_INT32_MAX) {
> +        apr_size_t old = val;
> +        val = apr_atomic_cas32(&worker->s->busy, val + 1, old);
> +        if (val == old) {
> +            break;
> +        }
> +    }
> +#elif APR_VERSION_AT_LEAST(1,7,4) /* APR 64bit atomics not safe before 1.7.4 
> */
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint64_t));
> +    val = apr_atomic_read64(&worker->s->busy);
> +    while (val < APR_INT64_MAX) {
> +        apr_size_t old = val;
> +        val = apr_atomic_cas64(&worker->s->busy, val + 1, old);
> +        if (val == old) {
> +            break;
> +        }
> +    }
> +#else /* Use atomics for (64bit) pointers */
> +    void *volatile *busy_p = (void *)&worker->s->busy;
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(void*));
> +    AP_DEBUG_ASSERT((apr_uintptr_t)busy_p % sizeof(void*) == 0);
> +    val = (apr_uintptr_t)apr_atomic_casptr((void *)busy_p, NULL, NULL);
> +    while (val < APR_INT64_MAX) {
> +        apr_size_t old = val;
> +        val = (apr_uintptr_t)apr_atomic_casptr((void *)busy_p,
> +                                               (void *)(apr_uintptr_t)(val + 
> 1),
> +                                               (void *)(apr_uintptr_t)old);
> +        if (val == old) {
> +            break;
> +        }
> +    }
> +#endif
> +}
> +
> +PROXY_DECLARE(apr_size_t) getbusy_count(proxy_worker *worker)
> +{
> +    apr_size_t val;
> +#if APR_SIZEOF_VOIDP == 4
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint32_t));
> +    val = apr_atomic_read32(&worker->s->busy);
> +#elif APR_VERSION_AT_LEAST(1,7,4) /* APR 64bit atomics not safe before 1.7.4 
> */
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint64_t));
> +    val = apr_atomic_read64(&worker->s->busy);
> +#else /* Use atomics for (64bit) pointers */
> +    void *volatile *busy_p = (void *)&worker->s->busy;
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(void*));
> +    AP_DEBUG_ASSERT((apr_uintptr_t)busy_p % sizeof(void*) == 0);
> +    val = (apr_uintptr_t)apr_atomic_casptr((void *)busy_p, NULL, NULL);
> +#endif
> +
> +    return val;
> +}
> +
> +PROXY_DECLARE(void) setbusy_count(proxy_worker *worker, apr_size_t to)
> +{
> +#if APR_SIZEOF_VOIDP == 4
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint32_t));
> +    apr_atomic_set32(&worker->s->busy, to);
> +#elif APR_VERSION_AT_LEAST(1,7,4) /* APR 64bit atomics not safe before 1.7.4 
> */
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(apr_uint64_t));
> +    apr_atomic_set64(&worker->s->busy, to);
> +#else /* Use atomics for (64bit) pointers */
> +    void *volatile *busy_p = (void *)&worker->s->busy;
> +    AP_DEBUG_ASSERT(sizeof(apr_size_t) == sizeof(void*));
> +    AP_DEBUG_ASSERT((apr_uintptr_t)busy_p % sizeof(void*) == 0);
> +    apr_atomic_xchgptr((void *)busy_p, (void *)(apr_uintptr_t)to);
> +#endif
> +}
> +
>  static void add_pollset(apr_pollset_t *pollset, apr_pollfd_t *pfd,
>                          apr_int16_t events)
>  {
> 

Regards

RĂ¼diger

Reply via email to