|
commit 6d79cedaaa4a16b2f42d2bf2bc25772a51354e91
|
|
Author: Willy Tarreau <w@1wt.eu>
|
|
Date: Wed Jul 24 17:42:44 2019 +0200
|
|
|
|
BUG/MINOR: proxy: always lock stop_proxy()
|
|
|
|
There is one unprotected call to stop_proxy() from the manage_proxy()
|
|
task, so there is a single caller by definition, but there is also
|
|
another such call from the CLI's "shutdown frontend" parser. This
|
|
one does it under the proxy's lock but the first one doesn't use it.
|
|
Thus it is theorically possible to corrupt the list of listeners in a
|
|
proxy by issuing "shutdown frontend" and SIGUSR1 exactly at the same
|
|
time. While it sounds particularly contrived or stupid, it could
|
|
possibly happen with automated tools that would send actions via
|
|
various channels. This could cause the process to loop forever or
|
|
to crash and thus stop faster than expected.
|
|
|
|
This might be backported as far as 1.8.
|
|
|
|
(cherry picked from commit 3de3cd4d9761324b31d23eb2c4a9434ed33801b8)
|
|
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
|
|
|
|
diff --git a/src/proxy.c b/src/proxy.c
|
|
index f669ebf1..ae761ead 100644
|
|
--- a/src/proxy.c
|
|
+++ b/src/proxy.c
|
|
@@ -1258,13 +1258,16 @@ void zombify_proxy(struct proxy *p)
|
|
* to be called when going down in order to release the ports so that another
|
|
* process may bind to them. It must also be called on disabled proxies at the
|
|
* end of start-up. If all listeners are closed, the proxy is set to the
|
|
- * PR_STSTOPPED state.
|
|
+ * PR_STSTOPPED state. The function takes the proxy's lock so it's safe to
|
|
+ * call from multiple places.
|
|
*/
|
|
void stop_proxy(struct proxy *p)
|
|
{
|
|
struct listener *l;
|
|
int nostop = 0;
|
|
|
|
+ HA_SPIN_LOCK(PROXY_LOCK, &p->lock);
|
|
+
|
|
list_for_each_entry(l, &p->conf.listeners, by_fe) {
|
|
if (l->options & LI_O_NOSTOP) {
|
|
HA_ATOMIC_ADD(&unstoppable_jobs, 1);
|
|
@@ -1278,6 +1281,8 @@ void stop_proxy(struct proxy *p)
|
|
}
|
|
if (!nostop)
|
|
p->state = PR_STSTOPPED;
|
|
+
|
|
+ HA_SPIN_UNLOCK(PROXY_LOCK, &p->lock);
|
|
}
|
|
|
|
/* This function resumes listening on the specified proxy. It scans all of its
|
|
@@ -2110,10 +2115,7 @@ static int cli_parse_shutdown_frontend(char **args, char *payload, struct appctx
|
|
send_log(px, LOG_WARNING, "Proxy %s stopped (FE: %lld conns, BE: %lld conns).\n",
|
|
px->id, px->fe_counters.cum_conn, px->be_counters.cum_conn);
|
|
|
|
- HA_SPIN_LOCK(PROXY_LOCK, &px->lock);
|
|
stop_proxy(px);
|
|
- HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock);
|
|
-
|
|
return 1;
|
|
}
|
|
|