diff --git a/include/haproxy/cfgparse.h b/include/haproxy/cfgparse.h index 56535b783..161b7d31d 100644 --- a/include/haproxy/cfgparse.h +++ b/include/haproxy/cfgparse.h @@ -111,6 +111,7 @@ extern char *cursection; extern int non_global_section_parsed; extern struct proxy *curproxy; +extern struct proxy *last_defproxy; extern char initial_cwd[PATH_MAX]; int cfg_parse_global(const char *file, int linenum, char **args, int inv); diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index ebea79385..bcb085936 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -299,7 +299,6 @@ int cfg_parse_listen_match_option(const char *file, int linenum, int kwm, int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) { static struct proxy *curr_defproxy = NULL; - static struct proxy *last_defproxy = NULL; const char *err; int rc; int err_code = 0; @@ -388,35 +387,49 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) err_code |= ERR_ALERT | ERR_FATAL; } - if (*args[1] && rc & PR_CAP_DEF) { - /* for default proxies, if another one has the same - * name and was explicitly referenced, this is an error - * that we must reject. E.g. - * defaults def - * backend bck from def - * defaults def + if (rc & PR_CAP_DEF) { + /* If last defaults is unnamed, it will be made + * invisible by the current newer section. It must be + * freed unless it is still referenced by proxies. */ - curproxy = proxy_find_by_name(args[1], PR_CAP_DEF, 0); - if (curproxy && curproxy->flags & PR_FL_EXPLICIT_REF) { - ha_alert("Parsing [%s:%d]: %s '%s' has the same name as another defaults section declared at" - " %s:%d which was explicitly referenced hence cannot be replaced. Please remove or" - " rename one of the offending defaults section.\n", - file, linenum, proxy_cap_str(rc), args[1], - curproxy->conf.file, curproxy->conf.line); - err_code |= ERR_ALERT | ERR_ABORT; - goto out; + if (last_defproxy && last_defproxy->id[0] == '\0' && + !last_defproxy->conf.refcount) { + defaults_px_destroy(last_defproxy); } + last_defproxy = NULL; - /* if the other proxy exists, we don't need to keep it - * since neither will support being explicitly referenced - * so let's drop it from the index but keep a reference to - * its location for error messages. - */ - if (curproxy) { - file_prev = curproxy->conf.file; - line_prev = curproxy->conf.line; - defaults_px_detach(curproxy); - curproxy = NULL; + /* If current defaults is named, check collision with previous instances. */ + if (*args[1]) { + curproxy = proxy_find_by_name(args[1], PR_CAP_DEF, 0); + + /* for default proxies, if another one has the same + * name and was explicitly referenced, this is an error + * that we must reject. E.g. + * defaults def + * backend bck from def + * defaults def + */ + if (curproxy && curproxy->flags & PR_FL_EXPLICIT_REF) { + ha_alert("Parsing [%s:%d]: %s '%s' has the same name as another defaults section declared at" + " %s:%d which was explicitly referenced hence cannot be replaced. Please remove or" + " rename one of the offending defaults section.\n", + file, linenum, proxy_cap_str(rc), args[1], + curproxy->conf.file, curproxy->conf.line); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + + /* if the other proxy exists, we don't need to keep it + * since neither will support being explicitly referenced + * so let's drop it from the index but keep a reference to + * its location for error messages. + */ + if (curproxy) { + file_prev = curproxy->conf.file; + line_prev = curproxy->conf.line; + defaults_px_detach(curproxy); + curproxy = NULL; + } } } diff --git a/src/cfgparse.c b/src/cfgparse.c index edc9c518f..1940330a7 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -110,6 +110,8 @@ extern struct proxy *mworker_proxy; /* curproxy is only valid during parsing and will be NULL afterwards. */ struct proxy *curproxy = NULL; +/* last defaults section parsed, NULL after parsing */ +struct proxy *last_defproxy = NULL; char *cursection = NULL; int cfg_maxpconn = 0; /* # of simultaneous connections per proxy (-N) */ diff --git a/src/haproxy.c b/src/haproxy.c index 95b2019d9..929a86537 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2098,6 +2098,13 @@ static void step_init_2(int argc, char** argv) struct pre_check_fct *prcf; const char *cc, *cflags, *opts; + /* Free last defaults if it is unnamed and unreferenced. */ + if (last_defproxy && last_defproxy->id[0] == '\0' && + !last_defproxy->conf.refcount) { + defaults_px_destroy(last_defproxy); + } + last_defproxy = NULL; /* This variable is not used after parsing. */ + /* destroy unreferenced defaults proxies */ defaults_px_destroy_all_unref(); diff --git a/src/proxy.c b/src/proxy.c index b3aa60145..d828ded9c 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1718,7 +1718,8 @@ int setup_new_proxy(struct proxy *px, const char *name, unsigned int cap, char * px->cap = cap; px->last_change = ns_to_sec(now_ns); - if (name && !(cap & PR_CAP_INT)) + /* Internal proxies or with empty name are not stored in the named tree. */ + if (name && name[0] != '\0' && !(cap & PR_CAP_INT)) proxy_store_name(px); if (!(cap & PR_CAP_DEF))