diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h index 0b8ce6d38..0ec1fae66 100644 --- a/include/haproxy/proxy-t.h +++ b/include/haproxy/proxy-t.h @@ -316,6 +316,7 @@ struct proxy { unsigned long last_change; /* internal use only: last time the proxy state was changed */ struct list global_list; /* list member for global proxy list */ + struct list el; /* attach point in various list - currently used only on defaults_list for defaults section */ unsigned int maxconn; /* max # of active streams on the frontend */ diff --git a/include/haproxy/proxy.h b/include/haproxy/proxy.h index b0f10c99c..ad6f6905b 100644 --- a/include/haproxy/proxy.h +++ b/include/haproxy/proxy.h @@ -39,6 +39,7 @@ extern struct list proxies; extern struct ceb_root *used_proxy_id; /* list of proxy IDs in use */ extern unsigned int error_snapshot_id; /* global ID assigned to each error then incremented */ extern struct ceb_root *proxy_by_name; /* tree of proxies sorted by name */ +extern struct list defaults_list; /* all defaults proxies list */ extern const struct cfg_opt cfg_opts[]; extern const struct cfg_opt cfg_opts2[]; diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index 0c811a608..ebea79385 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -569,6 +569,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) } if (rc & PR_CAP_DEF) { + LIST_APPEND(&defaults_list, &curproxy->el); /* last and current proxies must be updated to this one */ curr_defproxy = last_defproxy = curproxy; } else { diff --git a/src/haproxy.c b/src/haproxy.c index c012c9d5c..95b2019d9 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2742,8 +2742,10 @@ void deinit(void) * they are respectively cleaned up in sink_deinit() and deinit_log_forward() */ - /* destroy all referenced defaults proxies */ - defaults_px_destroy_all_unref(); + /* All proxies are removed now, so every defaults should also be freed + * when their refcount reached zero. + */ + BUG_ON(!LIST_ISEMPTY(&defaults_list)); userlist_free(userlist); diff --git a/src/proxy.c b/src/proxy.c index a5bd572ad..b3aa60145 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -64,7 +64,7 @@ struct list proxies = LIST_HEAD_INIT(proxies); /* list of all proxies */ struct ceb_root *used_proxy_id = NULL; /* list of proxy IDs in use */ struct ceb_root *proxy_by_name = NULL; /* tree of proxies sorted by name */ struct ceb_root *defproxy_by_name = NULL; /* tree of default proxies sorted by name (dups possible) */ -struct proxy *orphaned_default_proxies = NULL; /* deleted ones with refcount != 0 */ +struct list defaults_list = LIST_HEAD_INIT(defaults_list); /* list of all defaults proxies */ unsigned int error_snapshot_id = 0; /* global ID assigned to each error then incremented */ /* CLI context used during "show servers {state|conn}" */ @@ -1500,6 +1500,7 @@ void init_new_proxy(struct proxy *p) memset(p, 0, sizeof(struct proxy)); p->obj_type = OBJ_TYPE_PROXY; LIST_INIT(&p->global_list); + LIST_INIT(&p->el); LIST_INIT(&p->acl); LIST_INIT(&p->http_req_rules); LIST_INIT(&p->http_res_rules); @@ -1628,29 +1629,11 @@ static void defaults_px_free(struct proxy *defproxy) */ void defaults_px_destroy(struct proxy *px) { - struct proxy *prev; - BUG_ON(!(px->cap & PR_CAP_DEF)); BUG_ON(px->conf.refcount != 0); cebis_item_delete(&defproxy_by_name, conf.name_node, id, px); - - /* If orphaned defaults list is not empty, it may contain instance. - * In this case it is necessary to manually remove it from the list. - */ - if (orphaned_default_proxies) { - if (orphaned_default_proxies == px) { - orphaned_default_proxies = px->next; - } - else { - for (prev = orphaned_default_proxies; - prev && prev->next != px; prev = prev->next) - ; - if (prev) - prev->next = px->next; - } - px->next = NULL; - } + LIST_DELETE(&px->el); defaults_px_free(px); free(px); @@ -1669,35 +1652,19 @@ void defaults_px_destroy_all_unref(void) if (!px->conf.refcount) defaults_px_destroy(px); } - - px = orphaned_default_proxies; - while (px) { - BUG_ON(!(px->cap & PR_CAP_DEF)); - nx = px->next; - if (!px->conf.refcount) - defaults_px_destroy(px); - px = nx; - } } /* Removes defaults from the name tree. This operation is useful when a * section is made invisible by a newer instance with the same name. If is - * not referenced it is freed immediately, else it is moved in defaults - * orphaned list. + * not referenced it is freed immediately, else it is kept in defaults_list. */ void defaults_px_detach(struct proxy *px) { BUG_ON(!(px->cap & PR_CAP_DEF)); - cebis_item_delete(&defproxy_by_name, conf.name_node, id, px); - if (px->conf.refcount) { - /* still referenced just append it to the orphaned list */ - px->next = orphaned_default_proxies; - orphaned_default_proxies = px; - } - else { + if (!px->conf.refcount) defaults_px_destroy(px); - } + /* If not destroyed, can still be accessed in . */ } /* Add a reference on the default proxy for the proxy Nothing is