]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mworker: support a configurable maximum number of reloads
authorWilliam Lallemand <wlallemand@haproxy.com>
Tue, 7 May 2019 15:49:33 +0000 (17:49 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 7 May 2019 17:09:01 +0000 (19:09 +0200)
This patch implements a new global parameter for the master-worker mode.
When setting the mworker-max-reloads value, a worker receive a SIGTERM
if its number of reloads is greater than this value.

doc/configuration.txt
include/proto/mworker.h
src/haproxy.c
src/mworker.c

index f2954a846d717c4d2ac281eef4d6b3c96b94a7fb..31aac447aa68b0358af668c3ea154a0e94d0f0e8 100644 (file)
@@ -571,6 +571,7 @@ The following keywords are supported in the "global" section :
    - log-tag
    - log-send-hostname
    - lua-load
+   - mworker-max-reloads
    - nbproc
    - nbthread
    - node
@@ -966,6 +967,13 @@ master-worker [no-exit-on-failure]
 
   See also "-W" in the management guide.
 
+mworker-max-reloads <number>
+  In master-worker mode, this option limits the number of time a worker can
+  survive to a reload. If the worker did not left after a reload, once its
+  number of reloads is greater than this number, the worker will receive a
+  SIGTERM. This option helps to keep under control the number of workers.
+  See also "show proc" in the Management Guide.
+
 nbproc <number>
   Creates <number> processes when going daemon. This requires the "daemon"
   mode. By default, only one process is created, which is the recommended mode
index bf8317f48d373a0e9af3beab95fee10ba15cf954..86f09049f53a8af0e85eb6d8f1bd143da3068eb6 100644 (file)
@@ -35,5 +35,6 @@ int mworker_child_nb();
 
 int mworker_ext_launch_all();
 
+void mworker_kill_max_reloads(int sig);
 
 #endif /* PROTO_MWORKER_H_ */
index 8ab0c2e6f439c4bb2fd1e619a5cc18f46dd905d5..4c371254e1ac76a18eb555981c1298d805d955cf 100644 (file)
@@ -2780,6 +2780,10 @@ int main(int argc, char **argv)
        if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
                nb_oldpids = tell_old_pids(oldpids_sig);
 
+       /* send a SIGTERM to workers who have a too high reloads number  */
+       if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
+               mworker_kill_max_reloads(SIGTERM);
+
        if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)) {
                nb_oldpids = 0;
                free(oldpids);
index abc67bd8b85d8b03b9e9acb833b172a86e9710a3..8df748d3fac38c8b07783b3af1f2c9844b177d91 100644 (file)
@@ -17,6 +17,7 @@
 #include <string.h>
 #include <sys/wait.h>
 
+#include <common/cfgparse.h>
 #include <common/initcall.h>
 #include <common/mini-clist.h>
 
@@ -41,6 +42,7 @@
 #endif
 
 static int exitcode = -1;
+static int max_reloads = -1; /* number max of reloads a worker can have until they are killed */
 
 /* ----- children processes handling ----- */
 
@@ -59,6 +61,16 @@ static void mworker_kill(int sig)
        }
 }
 
+void mworker_kill_max_reloads(int sig)
+{
+       struct mworker_proc *child;
+
+       list_for_each_entry(child, &proc_list, list) {
+               if (max_reloads != -1 && (child->options & PROC_O_TYPE_WORKER) &&
+                   (child->pid > 0) && (child->reloads > max_reloads))
+                       kill(child->pid, sig);
+       }
+}
 
 /* return 1 if a pid is a current child otherwise 0 */
 int mworker_current_child(int pid)
@@ -515,6 +527,41 @@ static int cli_parse_reload(char **args, char *payload, struct appctx *appctx, v
 }
 
 
+static int mworker_parse_global_max_reloads(char **args, int section_type, struct proxy *curpx,
+           struct proxy *defpx, const char *file, int linenum, char **err)
+{
+
+       int err_code = 0;
+
+       if (alertif_too_many_args(1, file, linenum, args, &err_code))
+               goto out;
+
+       if (*(args[1]) == 0) {
+               memprintf(err, "%sparsing [%s:%d] : '%s' expects an integer argument.\n", *err, file, linenum, args[0]);
+               err_code |= ERR_ALERT | ERR_FATAL;
+               goto out;
+       }
+
+       max_reloads = atol(args[1]);
+       if (max_reloads < 0) {
+               memprintf(err, "%sparsing [%s:%d] '%s' : invalid value %d, must be >= 0", *err, file, linenum, args[0], max_reloads);
+               err_code |= ERR_ALERT | ERR_FATAL;
+               goto out;
+       }
+
+out:
+       return err_code;
+}
+
+
+static struct cfg_kw_list mworker_kws = {{ }, {
+       { CFG_GLOBAL, "mworker-max-reloads", mworker_parse_global_max_reloads },
+       { 0, NULL, NULL },
+}};
+
+INITCALL1(STG_REGISTER, cfg_register_keywords, &mworker_kws);
+
+
 /* register cli keywords */
 static struct cli_kw_list cli_kws = {{ },{
        { { "@<relative pid>", NULL }, "@<relative pid> : send a command to the <relative pid> process", NULL, cli_io_handler_show_proc, NULL, NULL, ACCESS_MASTER_ONLY},