MEDIUM: proxy: centralize proxy status update and reporting
There are multiple ways a proxy may switch to the disabled state,
but now it's essentially once it loses its last listener. Instead
of keeping duplicate code around and reporting the state change
before actually seeing it, we now report it at the moment it's
performed (from the last listener leaving) which allows to remove
the message from all other places.
diff --git a/include/haproxy/proxy.h b/include/haproxy/proxy.h
index a33ed26..fe253bf 100644
--- a/include/haproxy/proxy.h
+++ b/include/haproxy/proxy.h
@@ -40,6 +40,7 @@
extern const struct cfg_opt cfg_opts2[];
struct task *manage_proxy(struct task *t, void *context, unsigned short state);
+void proxy_cond_disable(struct proxy *p);
void soft_stop(void);
int pause_proxy(struct proxy *p);
int resume_proxy(struct proxy *p);
diff --git a/src/listener.c b/src/listener.c
index e8f2a95..6368e37 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -354,11 +354,7 @@
if (l->state >= LI_ASSIGNED)
__delete_listener(l);
- if (px->li_ready + px->li_paused == 0) {
- px->disabled = 1;
- if (px->task)
- task_wakeup(px->task, TASK_WOKEN_MSG);
- }
+ proxy_cond_disable(px);
}
if (!lli)
diff --git a/src/proxy.c b/src/proxy.c
index 247ee63..a77ad0a 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -1045,6 +1045,46 @@
HA_SPIN_INIT(&p->lock);
}
+/* to be called under the proxy lock after stopping some listeners. This will
+ * automatically update the p->disabled flag after stopping the last one, and
+ * will emit a log indicating the proxy's condition. The function is idempotent
+ * so that it will not emit multiple logs; a proxy will be disabled only once.
+ */
+void proxy_cond_disable(struct proxy *p)
+{
+ if (p->disabled)
+ return;
+
+ if (p->li_ready + p->li_paused > 0)
+ return;
+
+ p->disabled = 1;
+
+ if (!(proc_mask(p->bind_proc) & pid_bit))
+ goto silent;
+
+ /* Note: syslog proxies use their own loggers so while it's somewhat OK
+ * to report them being stopped as a warning, we must not spam their log
+ * servers which are in fact production servers. For other types (CLI,
+ * peers, etc) we must not report them at all as they're not really on
+ * the data plane but on the control plane.
+ */
+ if (p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP || p->mode == PR_MODE_SYSLOG)
+ ha_warning("Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n",
+ p->id, p->fe_counters.cum_conn, p->be_counters.cum_conn);
+
+ if (p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP)
+ send_log(p, LOG_WARNING, "Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n",
+ p->id, p->fe_counters.cum_conn, p->be_counters.cum_conn);
+
+ silent:
+ if (p->table && p->table->size && p->table->sync_task)
+ task_wakeup(p->table->sync_task, TASK_WOKEN_MSG);
+
+ if (p->task)
+ task_wakeup(p->task, TASK_WOKEN_MSG);
+}
+
/*
* This is the proxy management task. It enables proxies when there are enough
* free streams, or stops them when the table is full. It is designed to be
@@ -1066,10 +1106,6 @@
int t;
t = tick_remain(now_ms, p->stop_time);
if (t == 0) {
- ha_warning("Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n",
- p->id, p->fe_counters.cum_conn, p->be_counters.cum_conn);
- send_log(p, LOG_WARNING, "Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n",
- p->id, p->fe_counters.cum_conn, p->be_counters.cum_conn);
stop_proxy(p);
/* try to free more memory */
pool_gc(NULL);
@@ -2069,11 +2105,6 @@
if (px->disabled)
return cli_msg(appctx, LOG_NOTICE, "Frontend was already shut down.\n");
- ha_warning("Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n",
- px->id, px->fe_counters.cum_conn, px->be_counters.cum_conn);
- send_log(px, LOG_WARNING, "Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n",
- px->id, px->fe_counters.cum_conn, px->be_counters.cum_conn);
-
stop_proxy(px);
return 1;
}