Please disregard, patch 1 calls thread_isolate() with a lock held. v2
follows.

On Tue, Oct 20, 2026 at 3:04 PM David Carlier <[email protected]> wrote:

> From: David Carlier <[email protected]>
>
> When da_haproxy_checkinst() hot-reloads the atlas, the old instance was
> closed and its image freed under dadwsch_lock only, while lookups on other
> threads take no lock. With several threads, a request could search a freed
> image or a partially copied atlas and crash or return wrong properties.
>
> The new atlas is still compiled outside of any isolation, then the swap is
> done between thread_isolate() and thread_release() and the old image is
> freed afterwards. The lock is now only tried, so other threads keep serving
> with the current atlas during the compilation instead of spinning.
>
> This should be backported to lower branches.
> ---
>  addons/deviceatlas/da.c | 28 ++++++++++++++++------------
>  1 file changed, 16 insertions(+), 12 deletions(-)
>
> diff --git a/addons/deviceatlas/da.c b/addons/deviceatlas/da.c
> index 55429a7c5..902ceaeaf 100644
> --- a/addons/deviceatlas/da.c
> +++ b/addons/deviceatlas/da.c
> @@ -6,6 +6,7 @@
>  #include <haproxy/api.h>
>  #include <haproxy/arg.h>
>  #include <haproxy/cfgparse.h>
> +#include <haproxy/clock.h>
>  #include <haproxy/errors.h>
>  #include <haproxy/global.h>
>  #include <haproxy/http.h>
> @@ -287,14 +288,15 @@ static void da_haproxy_checkinst(void)
>
>              if (base[0] != 0) {
>              FILE *jsonp;
> -            void *cnew;
> +            void *cnew, *cold;
>              da_status_t status;
>              size_t atlassz;
>              char atlasp[ATLASTOKSZ] = {0};
>              da_atlas_t inst;
>              da_property_decl_t extraprops[1] = {{NULL, 0}};
>  #ifdef USE_THREAD
> -            HA_SPIN_LOCK(OTHER_LOCK, &dadwsch_lock);
> +            if (HA_SPIN_TRYLOCK(OTHER_LOCK, &dadwsch_lock) != 0)
> +                return;
>              if (base[0] == 0) {
>                  HA_SPIN_UNLOCK(OTHER_LOCK, &dadwsch_lock);
>                  return;
> @@ -316,20 +318,22 @@ static void da_haproxy_checkinst(void)
>              fclose(jsonp);
>              if (status == DA_OK) {
>                  if (da_atlas_open(&inst, extraprops, cnew, atlassz) ==
> DA_OK) {
> +                    size_t hi, maxhdrlen = 16;
> +
>                      inst.config.cache_size = global_deviceatlas.cachesize;
> +                    for (hi = 0; hi < inst.header_evidence_count; hi++) {
> +                        size_t nl =
> strlen(inst.header_priorities[hi].name);
> +                        if (nl > maxhdrlen)
> +                            maxhdrlen = nl;
> +                    }
> +                    thread_isolate();
>                      da_atlas_close(&global_deviceatlas.atlas);
> -                    free(global_deviceatlas.atlasimgptr);
> +                    cold = global_deviceatlas.atlasimgptr;
>                      global_deviceatlas.atlasimgptr = cnew;
>                      global_deviceatlas.atlas = inst;
> -                    {
> -                        size_t hi;
> -                        global_deviceatlas.maxhdrlen = 16;
> -                        for (hi = 0; hi < inst.header_evidence_count;
> hi++) {
> -                            size_t nl =
> strlen(inst.header_priorities[hi].name);
> -                            if (nl > global_deviceatlas.maxhdrlen)
> -                                global_deviceatlas.maxhdrlen = nl;
> -                        }
> -                    }
> +                    global_deviceatlas.maxhdrlen = maxhdrlen;
> +                    thread_release();
> +                    free(cold);
>                      base[0] = 0;
>                      ha_notice("deviceatlas : new instance, data file date
> `%s`.\n",
>
>  da_getdatacreationiso8601(&global_deviceatlas.atlas));
> --
> 2.55.0
>
>

Reply via email to