From 7067b3a92efc9c9a7c3239245fdc96ea7310f46a Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 2 Jun 2019 11:11:29 +0200 Subject: [PATCH] BUG/MINOR: deinit/threads: make hard-stop-after perform a clean exit As reported in GH issue #99, when hard-stop-after triggers and threads are in use, the chance that any thread releases the resources in use by the other ones is non-null. Thus no thread should be allowed to deinit() nor exit by itself. Here we take a different approach. We simply use a 3rd possible value for the "killed" variable so that all threads know they must break out of the run-poll-loop and immediately stop. This patch was tested by commenting the stream_shutdown() calls in hard_stop() to increase the chances to see a stream use released resources. With this fix applied, it never crashes anymore. This fix should be backported to 1.9 and 1.8. --- include/types/global.h | 2 +- src/haproxy.c | 4 ++++ src/proxy.c | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/types/global.h b/include/types/global.h index a87b40722..5fca648af 100644 --- a/include/types/global.h +++ b/include/types/global.h @@ -233,7 +233,7 @@ extern const int zero; extern const int one; extern const struct linger nolinger; extern int stopping; /* non zero means stopping in progress */ -extern int killed; /* non zero means a hard-stop is triggered */ +extern int killed; /* >0 means a hard-stop is triggered, >1 means hard-stop immediately */ extern char hostname[MAX_HOSTNAME_LEN]; extern char localpeer[MAX_HOSTNAME_LEN]; extern struct list global_listener_queue; /* list of the temporarily limited listeners */ diff --git a/src/haproxy.c b/src/haproxy.c index df9a68600..9c93bed33 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2524,6 +2524,10 @@ static void run_poll_loop() if ((jobs - unstoppable_jobs) == 0) break; + /* also stop if we failed to cleanly stop all tasks */ + if (killed > 1) + break; + /* expire immediately if events are pending */ wake = 1; if (fd_cache_mask & tid_bit) diff --git a/src/proxy.c b/src/proxy.c index 9fda6e2d1..575a8eff6 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1071,9 +1071,9 @@ struct task *hard_stop(struct task *t, void *context, unsigned short state) if (killed) { ha_warning("Some tasks resisted to hard-stop, exiting now.\n"); send_log(NULL, LOG_WARNING, "Some tasks resisted to hard-stop, exiting now.\n"); - /* Do some cleanup and explicitly quit */ - deinit(); - exit(0); + killed = 2; + t->expire = TICK_ETERNITY; + return t; } ha_warning("soft-stop running for too long, performing a hard-stop.\n");