diff --git a/include/haproxy/uri_auth-t.h b/include/haproxy/uri_auth-t.h index 009adfdfe..b2d829ab0 100644 --- a/include/haproxy/uri_auth-t.h +++ b/include/haproxy/uri_auth-t.h @@ -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 */ diff --git a/include/haproxy/uri_auth.h b/include/haproxy/uri_auth.h index ae5dbb04a..3b61e8fff 100644 --- a/include/haproxy/uri_auth.h +++ b/include/haproxy/uri_auth.h @@ -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 */ diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index bb722b3ee..760ca7167 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -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; diff --git a/src/cfgparse.c b/src/cfgparse.c index c29b6f6db..de5405a9a 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -90,7 +90,7 @@ #include #include #include -#include +#include /* 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; } diff --git a/src/haproxy.c b/src/haproxy.c index 56bd38b46..43b282bd5 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -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(); diff --git a/src/proxy.c b/src/proxy.c index 9850d45a5..6f951cd50 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -54,6 +54,7 @@ #include #include #include +#include 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) { diff --git a/src/uri_auth.c b/src/uri_auth.c index a487ed375..eddb1a0a5 100644 --- a/src/uri_auth.c +++ b/src/uri_auth.c @@ -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