]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: uri_auth: implement clean uri_auth cleaning
authorAurelien DARRAGON <adarragon@haproxy.com>
Wed, 13 Nov 2024 18:54:32 +0000 (19:54 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Thu, 14 Nov 2024 14:03:38 +0000 (15:03 +0100)
proxy auth_uri struct was manually cleaned up during deinit, but the logic
behind was kind of akward because it was required to find out which ones
were shared or not. Instead, let's switch to a proper refcount mechanism
and free the auth_uri struct directly in proxy_free_common().

include/haproxy/uri_auth-t.h
include/haproxy/uri_auth.h
src/cfgparse-listen.c
src/cfgparse.c
src/haproxy.c
src/proxy.c
src/uri_auth.c

index 009adfdfe6ac1dcbe97a8e3140a42a6967b2463a..b2d829ab006fb9be21ed209da097f97a169cc2bd 100644 (file)
@@ -29,6 +29,7 @@ struct stat_scope {
 /* later we may link them to support multiple URI matching */
 struct uri_auth {
        int uri_len;                    /* the prefix length */
+       uint refcount;                  /* to free when unused */
        char *uri_prefix;               /* the prefix we want to match */
        char *auth_realm;               /* the realm reported to the client */
        char *node, *desc;              /* node name & description reported in this stats */
index ae5dbb04a0c2c3582319c9f9d194e33199b87ee2..3b61e8fff251e3af0e15989921c6e0c14f439c3c 100644 (file)
@@ -34,6 +34,8 @@ struct uri_auth *stats_add_scope(struct uri_auth **root, char *scope);
 struct uri_auth *stats_set_node(struct uri_auth **root, char *name);
 struct uri_auth *stats_set_desc(struct uri_auth **root, char *desc);
 void stats_uri_auth_free(struct uri_auth *uri_auth);
+void stats_uri_auth_take(struct uri_auth *uri_auth);
+void stats_uri_auth_drop(struct uri_auth *uri_auth);
 
 #endif /* _HAPROXY_URI_AUTH_H */
 
index bb722b3eef3c59b5c83c00122320c52be76699b9..760ca716712959378ad1a0e6536698ef3f38c90f 100644 (file)
@@ -1761,8 +1761,11 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                        LIST_APPEND(&curproxy->sticking_rules, &rule->list);
        }
        else if (strcmp(args[0], "stats") == 0) {
-               if (!(curproxy->cap & PR_CAP_DEF) && curproxy->uri_auth == curr_defproxy->uri_auth)
-                       curproxy->uri_auth = NULL; /* we must detach from the default config */
+               if (!(curproxy->cap & PR_CAP_DEF) && curproxy->uri_auth == curr_defproxy->uri_auth) {
+                       /* we must detach from the default config */
+                       stats_uri_auth_drop(curproxy->uri_auth);
+                       curproxy->uri_auth = NULL;
+               }
 
                if (!*args[1]) {
                        goto stats_error_parsing;
index c29b6f6dbae125693651fd2c832e611cb2255f5d..de5405a9a427a3e17e4e50553aa0011f39f7e077 100644 (file)
@@ -90,7 +90,7 @@
 #include <haproxy/tcpcheck.h>
 #include <haproxy/thread.h>
 #include <haproxy/tools.h>
-#include <haproxy/uri_auth-t.h>
+#include <haproxy/uri_auth.h>
 
 
 /* Used to chain configuration sections definitions. This list
@@ -3936,6 +3936,7 @@ out_uri_auth_compat:
                                ha_warning("'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
                                           proxy_type_str(curproxy), curproxy->id);
                                err_code |= ERR_WARN;
+                               stats_uri_auth_drop(curproxy->uri_auth);
                                curproxy->uri_auth = NULL;
                        }
 
index 56bd38b4651402554325230bbbcfc55ba087ca17..43b282bd54e6f64a1ea57c5d8fdef100003ae53f 100644 (file)
@@ -3200,7 +3200,6 @@ void deinit(void)
 {
        struct proxy *p = proxies_list, *p0;
        struct cfgfile *cfg, *cfg_tmp;
-       struct uri_auth *uap, *ua = NULL;
        struct logger *log, *logb;
        struct build_opts_str *bol, *bolb;
        struct post_deinit_fct *pdf, *pdfb;
@@ -3254,22 +3253,6 @@ void deinit(void)
 
        deinit_signals();
        while (p) {
-               /* build a list of unique uri_auths */
-               if (!ua)
-                       ua = p->uri_auth;
-               else {
-                       /* check if p->uri_auth is unique */
-                       for (uap = ua; uap; uap=uap->next)
-                               if (uap == p->uri_auth)
-                                       break;
-
-                       if (!uap && p->uri_auth) {
-                               /* add it, if it is */
-                               p->uri_auth->next = ua;
-                               ua = p->uri_auth;
-                       }
-               }
-
                p0 = p;
                p = p->next;
                free_proxy(p0);
@@ -3282,12 +3265,6 @@ void deinit(void)
        /* destroy all referenced defaults proxies  */
        proxy_destroy_all_unref_defaults();
 
-       while (ua) {
-               uap = ua;
-               ua = ua->next;
-               stats_uri_auth_free(uap);
-       }
-
        userlist_free(userlist);
 
        cfg_unregister_sections();
index 9850d45a5ba4872dc028acf9d0228a3857058a80..6f951cd506fe6a1933543c1a33669eddb99e17c5 100644 (file)
@@ -54,6 +54,7 @@
 #include <haproxy/tcpcheck.h>
 #include <haproxy/time.h>
 #include <haproxy/tools.h>
+#include <haproxy/uri_auth.h>
 
 
 int listeners; /* # of proxy listeners, set by cfgparse */
@@ -271,6 +272,8 @@ static inline void proxy_free_common(struct proxy *px)
        }
 
        free_email_alert(px);
+       stats_uri_auth_drop(px->uri_auth);
+       px->uri_auth = NULL;
 }
 
 void free_proxy(struct proxy *p)
@@ -1513,10 +1516,6 @@ void proxy_free_defaults(struct proxy *defproxy)
 
        proxy_release_conf_errors(defproxy);
        deinit_proxy_tcpcheck(defproxy);
-
-       /* FIXME: we cannot free uri_auth because it might already be used by
-        * another proxy (legacy code for stats URI ...). Refcount anyone ?
-        */
 }
 
 /* delete a defproxy from the tree if still in it, frees its content and its
@@ -1803,7 +1802,11 @@ static int proxy_defproxy_cpy(struct proxy *curproxy, const struct proxy *defpro
        }
 
        curproxy->mode = defproxy->mode;
-       curproxy->uri_auth = defproxy->uri_auth; /* for stats */
+
+       /* for stats */
+       stats_uri_auth_drop(curproxy->uri_auth);
+       stats_uri_auth_take(defproxy->uri_auth);
+       curproxy->uri_auth = defproxy->uri_auth;
 
        /* copy default loggers to curproxy */
        list_for_each_entry(tmplogger, &defproxy->loggers, list) {
index a487ed3755624e79dde8b4fa32fc8302af394563..eddb1a0a507fecbd856a6a08d9d3ddf805f294bf 100644 (file)
@@ -38,6 +38,7 @@ struct uri_auth *stats_check_init_uri_auth(struct uri_auth **root)
 
                LIST_INIT(&u->http_req_rules);
                LIST_INIT(&u->admin_rules);
+               stats_uri_auth_take(u);
        } else
                u = *root;
 
@@ -342,6 +343,21 @@ void stats_uri_auth_free(struct uri_auth *uri_auth)
        free(uri_auth);
 }
 
+void stats_uri_auth_drop(struct uri_auth *uri_auth)
+{
+       if (!uri_auth)
+               return;
+       if (HA_ATOMIC_SUB_FETCH(&uri_auth->refcount, 1) == 0)
+               stats_uri_auth_free(uri_auth);
+}
+
+void stats_uri_auth_take(struct uri_auth *uri_auth)
+{
+       if (!uri_auth)
+               return;
+       HA_ATOMIC_INC(&uri_auth->refcount);
+}
+
 /*
  * Local variables:
  *  c-indent-level: 8