#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;
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);
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);
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);
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
lua_close(hlua_states[thr]);
}
- free_proxy(socket_proxy);
+ proxy_drop(socket_proxy);
}
REGISTER_POST_DEINIT(hlua_deinit);
if (err_code & ERR_CODE) {
ha_alert("httpclient: cannot initialize: %s\n", errmsg);
free(errmsg);
- free_proxy(px);
+ proxy_drop(px);
return NULL;
}
while (p) {
p0 = p;
p = p->next;
- free_proxy(p0);
+ proxy_drop(p0);
}
}
proxy_unref_defaults(p);
}
-/* deinit and free <p> proxy */
-void free_proxy(struct proxy *p)
+/* Decrement <p> 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);
}
if (!setup_new_proxy(curproxy, name, cap, errmsg))
goto fail;
+ proxy_take(curproxy);
+
done:
return curproxy;
return NULL;
}
+/* Increment <px> refcount. Does nothing for a default proxy instance. */
+void proxy_take(struct proxy *px)
+{
+ if (!(px->cap & PR_CAP_DEF))
+ HA_ATOMIC_INC(&px->refcount);
+}
+
/* post-check for proxies */
static int proxy_postcheck(struct proxy *px)
{
return 1;
err:
- /* free_proxy() ensures any potential refcounting on defpx is decremented. */
- free_proxy(px);
+ /* This ensures any potential refcounting on defpx is decremented. */
+ proxy_drop(px);
thread_release();
if (msg) {
goto out;
}
+ px->flags |= PR_FL_DELETED;
+
thread_release();
ha_notice("Backend deleted.\n");
resolv_free_resolution(res);
}
- free_proxy(resolvers->px);
+ proxy_drop(resolvers->px);
free(resolvers->id);
free((char *)resolvers->conf.file);
task_destroy(resolvers->t);
err_free_conf_file:
ha_free((void **)&r->conf.file);
err_free_p:
- free_proxy(p);
+ proxy_drop(p);
err_free_r:
ha_free(&r);
return err_code;
}
LIST_DEL_INIT(&sink->sink_list); // remove from parent list
task_destroy(sink->forward_task);
- free_proxy(sink->forward_px);
+ proxy_drop(sink->forward_px);
ha_free(&sink->name);
ha_free(&sink->desc);
while (sink->sft) {
return sink;
err:
- free_proxy(p);
+ proxy_drop(p);
return NULL;
}