MINOR: mworker: support a configurable maximum number of reloads
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.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index f2954a8..31aac44 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -571,6 +571,7 @@
- log-tag
- log-send-hostname
- lua-load
+ - mworker-max-reloads
- nbproc
- nbthread
- node
@@ -966,6 +967,13 @@
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
diff --git a/include/proto/mworker.h b/include/proto/mworker.h
index bf8317f..86f0904 100644
--- a/include/proto/mworker.h
+++ b/include/proto/mworker.h
@@ -35,5 +35,6 @@
int mworker_ext_launch_all();
+void mworker_kill_max_reloads(int sig);
#endif /* PROTO_MWORKER_H_ */
diff --git a/src/haproxy.c b/src/haproxy.c
index 8ab0c2e..4c37125 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -2780,6 +2780,10 @@
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);
diff --git a/src/mworker.c b/src/mworker.c
index abc67bd..8df748d 100644
--- a/src/mworker.c
+++ b/src/mworker.c
@@ -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 @@
}
}
+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 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},