diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h index fcf9732bd..c233d2909 100644 --- a/include/haproxy/proxy-t.h +++ b/include/haproxy/proxy-t.h @@ -247,6 +247,7 @@ enum PR_SRV_STATE_FILE { #define PR_FL_PAUSED 0x00000020 /* The proxy was paused at run time (reversible) */ #define PR_FL_CHECKED 0x00000040 /* The proxy configuration was fully checked (including postparsing checks) */ #define PR_FL_BE_UNPUBLISHED 0x00000080 /* The proxy cannot be targetted by content switching rules */ +#define PR_FL_DELETED 0x00000100 /* Proxy has been deleted and must be manipulated with care */ struct stream; @@ -508,6 +509,7 @@ struct proxy { struct guid_node guid; /* GUID global tree node */ struct mt_list watcher_list; /* list of elems which currently references this proxy instance (currently only used with backends) */ + uint refcount; /* refcount to keep proxy from being deleted during runtime */ EXTRA_COUNTERS(extra_counters_fe); EXTRA_COUNTERS(extra_counters_be); diff --git a/include/haproxy/proxy.h b/include/haproxy/proxy.h index fa19924f7..5b73b25d4 100644 --- a/include/haproxy/proxy.h +++ b/include/haproxy/proxy.h @@ -58,7 +58,7 @@ void stop_proxy(struct proxy *p); int stream_set_backend(struct stream *s, struct proxy *be); void deinit_proxy(struct proxy *p); -void free_proxy(struct proxy *p); +void proxy_drop(struct proxy *p); const char *proxy_cap_str(int cap); const char *proxy_mode_str(int mode); enum pr_mode str_to_proxy_mode(const char *mode); @@ -82,6 +82,7 @@ void proxy_unref_defaults(struct proxy *px); int setup_new_proxy(struct proxy *px, const char *name, unsigned int cap, char **errmsg); struct proxy *alloc_new_proxy(const char *name, unsigned int cap, char **errmsg); +void proxy_take(struct proxy *px); struct proxy *parse_new_proxy(const char *name, unsigned int cap, const char *file, int linenum, const struct proxy *defproxy); diff --git a/src/haproxy.c b/src/haproxy.c index 49640f6eb..9b13bd2f3 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2814,7 +2814,7 @@ void deinit(void) while (p) { p0 = p; p = p->next; - free_proxy(p0); + proxy_drop(p0); }/* end while(p) */ /* we don't need to free sink_proxies_list nor cfg_log_forward proxies since diff --git a/src/hlua.c b/src/hlua.c index 52884221a..764c0fb84 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -14726,7 +14726,7 @@ static void hlua_deinit() lua_close(hlua_states[thr]); } - free_proxy(socket_proxy); + proxy_drop(socket_proxy); } REGISTER_POST_DEINIT(hlua_deinit); diff --git a/src/http_client.c b/src/http_client.c index 64fbc8707..762fc0946 100644 --- a/src/http_client.c +++ b/src/http_client.c @@ -1214,7 +1214,7 @@ err: if (err_code & ERR_CODE) { ha_alert("httpclient: cannot initialize: %s\n", errmsg); free(errmsg); - free_proxy(px); + proxy_drop(px); return NULL; } diff --git a/src/log.c b/src/log.c index 9fc0d86aa..f26079b22 100644 --- a/src/log.c +++ b/src/log.c @@ -3739,7 +3739,7 @@ void deinit_log_forward() while (p) { p0 = p; p = p->next; - free_proxy(p0); + proxy_drop(p0); } } diff --git a/src/proxy.c b/src/proxy.c index f9241ea1d..04982b705 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -456,9 +456,19 @@ void deinit_proxy(struct proxy *p) proxy_unref_defaults(p); } -/* deinit and free
proxy */ -void free_proxy(struct proxy *p) +/* Decrement
refcount and free it if null. For a default proxy instance,
+ * refcount is ignored and free is immediately performed.
+ */
+void proxy_drop(struct proxy *p)
{
+ if (!p)
+ return;
+
+ if (!(p->cap & PR_CAP_DEF)) {
+ if (HA_ATOMIC_SUB_FETCH(&p->refcount, 1))
+ return;
+ }
+
deinit_proxy(p);
ha_free(&p);
}
@@ -3211,6 +3221,8 @@ struct proxy *alloc_new_proxy(const char *name, unsigned int cap, char **errmsg)
if (!setup_new_proxy(curproxy, name, cap, errmsg))
goto fail;
+ proxy_take(curproxy);
+
done:
return curproxy;
@@ -3225,6 +3237,13 @@ struct proxy *alloc_new_proxy(const char *name, unsigned int cap, char **errmsg)
return NULL;
}
+/* Increment