Several use cases may accept to abruptly close the connections when the
instance is stopping instead of waiting for timeouts to happen.
This option allows to specify a grace period which defines the maximum
time to spend to perform a soft-stop (occuring when SIGUSR1 is
received).
With this global option defined in the configuration, once all connections are
closed or the grace time is reached, the instance will quit.
---
doc/configuration.txt | 12 ++++++++++++
include/types/global.h | 2 ++
src/cfgparse.c | 17 +++++++++++++++++
src/haproxy.c | 8 ++++++++
src/proxy.c | 2 ++
5 files changed, 41 insertions(+)
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 228e8132..b1109906 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -535,6 +535,7 @@ The following keywords are supported in the "global"
section :
- deviceatlas-properties-cookie
- external-check
- gid
+ - grace
- group
- log
- log-tag
@@ -703,6 +704,17 @@ gid <number>
will only be able to drop these groups if started with superuser privileges.
See also "group" and "uid".
+grace <time>
+ Defines the grace time allowed to perform a clean soft-stop.
+
+ Arguments :
+ <time> is the maximum time (by default in milliseconds) for which the
+ instance will remain alive when a soft-stop is received via the
+ SIGUSR1 signal.
+
+ This may be used to ensure that the instance will quit even if connections
+ remain opened (for example with long timeouts for a proxy in tcp mode).
+
group <group name>
Similar to "gid" but uses the GID of group name <group name> from /etc/group.
See also "gid" and "user".
diff --git a/include/types/global.h b/include/types/global.h
index e14a2add..1d273bf4 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -80,6 +80,7 @@ struct global {
int gid;
int external_check;
int nbproc;
+ unsigned int grace; /* grace period to process soft stop */
int maxconn, hardmaxconn;
int maxsslconn;
int ssl_session_max_cost; /* how many bytes an SSL session may cost */
@@ -170,6 +171,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 grace;
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/cfgparse.c b/src/cfgparse.c
index 2eb25edb..8b6855f7 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -1011,6 +1011,23 @@ int cfg_parse_global(const char *file, int linenum, char
**args, int kwm)
}
}
/* end of user/group name handling*/
+ else if (strcmp(args[0], "grace") == 0) {
+ const char *res;
+
+ if (!*args[1]) {
+ Alert("parsing [%s:%d] : '%s' expects <time> as
argument.\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ res = parse_time_err(args[1], &global.grace, TIME_UNIT_MS);
+ if (res) {
+ Alert("parsing [%s:%d]: unexpected character '%c' in
argument to <%s>.\n",
+ file, linenum, *res, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
else if (!strcmp(args[0], "nbproc")) {
if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto out;
diff --git a/src/haproxy.c b/src/haproxy.c
index 559b4811..400fb7e7 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -118,6 +118,7 @@ int relative_pid = 1; /* process id starting
at 1 */
/* global options */
struct global global = {
.nbproc = 1,
+ .grace = TICK_ETERNITY,
.req_count = 0,
.logsrvs = LIST_HEAD_INIT(global.logsrvs),
.maxzlibmem = 0,
@@ -158,6 +159,7 @@ struct global global = {
int stopping; /* non zero means stopping in progress */
int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...)
*/
+int grace = TICK_ETERNITY;
/* Here we store informations about the pids of the processes we may pause
* or kill. We will send them a signal every 10 ms until we can bind to all
@@ -1585,6 +1587,12 @@ static void run_poll_loop()
/* Check if we can expire some tasks */
next = wake_expired_tasks();
+ if (stopping && (grace != TICK_ETERNITY)) {
+ if (tick_is_expired(grace, now_ms))
+ break;
+ if (next == TICK_ETERNITY || tick_is_expired(next,
grace))
+ next = grace;
+ }
/* stop when there's nothing left to do */
if (jobs == 0)
diff --git a/src/proxy.c b/src/proxy.c
index c76d55d5..024b36fa 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -925,6 +925,8 @@ void soft_stop(void)
struct peers *prs;
stopping = 1;
+ if (global.grace != TICK_ETERNITY)
+ grace = tick_add(now_ms, global.grace);
p = proxy;
tv_update_date(0,1); /* else, the old time before select will be used */
while (p) {
--
2.11.0