]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mworker/cli: add _send_status to support state transition
authorValentine Krasnobaeva <vkrasnobaeva@haproxy.com>
Wed, 2 Oct 2024 12:48:01 +0000 (14:48 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 16 Oct 2024 20:02:39 +0000 (22:02 +0200)
In the new master-worker architecture, when a worker process is forked and
successfully initialized it needs somehow to communicate its "READY" state to
the master, in order to terminate the previous worker and workers, that might
exceeded max_reloads counter.

So, let's implement for this a new master CLI _send_status command. A new
worker can send its status string "READY" to the master, when it's about
entering to the run poll loop, thus it can start to receive data.

In _send_status() in the master context we update the status of the new worker:
PROC_O_INIT flag is withdrawn.

When TERM signal is sent to a worker, worker terminates and this triggers the
mworker_catch_sigchld() handler in master. This handler deletes the exiting
process entry from the processes list.

In _send_status() we loop over the processes list twice. At the first time, in
order to stop workers that exceeded the max_reloads counter. At the second time,
in order to stop the worker forked before the last reload. In the corner case,
when max_reloads=1, we avoid to send SIGTERM twice to the same worker by
setting sigterm_sent flag during the first loop.

include/haproxy/global.h
include/haproxy/mworker.h
src/cli.c
src/haproxy.c
src/mworker.c

index 17cfff3ae931431255f9a0e6c64d1a2a89017b32..f5c2628d1e70182101ffb98d0fb1fb2b06064fd6 100644 (file)
@@ -35,6 +35,7 @@ extern int  unstoppable_jobs;   /* # of active jobs that can't be stopped during
 extern int  active_peers;       /* # of active peers (connection attempts and successes) */
 extern int  connected_peers;    /* # of really connected peers */
 extern int nb_oldpids;          /* contains the number of old pids found */
+extern int oldpids_sig;         /* signal to sent in order to stop the previous (old) process */
 extern const int zero;
 extern const int one;
 extern const struct linger nolinger;
index 0251a9de27795e39534c23afcf745382da550819..72c5f94a12b06a8ba174dcba1e99dd5b514b206d 100644 (file)
@@ -17,6 +17,7 @@
 #include <haproxy/mworker-t.h>
 #include <haproxy/signal-t.h>
 
+extern int max_reloads;
 extern struct mworker_proc *proc_self;
 /* master CLI configuration (-S flag) */
 extern struct list mworker_cli_conf;
index bbd11c1d12c3f23b02f76cfecc4fdc4dd20c6f87..11fc1b5616afcd087bed40710838ab63d6cad032 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -2463,6 +2463,42 @@ static int cli_parse_simple(char **args, char *payload, struct appctx *appctx, v
        return 1;
 }
 
+static int _send_status(char **args, char *payload, struct appctx *appctx, void *private)
+{
+       struct mworker_proc *proc;
+       int pid;
+
+       BUG_ON((strcmp(args[0], "_send_status") != 0),
+               "Triggered in _send_status by unsupported command name.\n");
+
+       pid = atoi(args[2]);
+
+       list_for_each_entry(proc, &proc_list, list) {
+               /* update status of the new worker */
+               if (proc->pid == pid)
+                       proc->options &= ~PROC_O_INIT;
+               /* send TERM to workers, which have exceeded max_reloads counter */
+               if (max_reloads != -1) {
+                       if ((proc->options & PROC_O_TYPE_WORKER) &&
+                               (proc->options & PROC_O_LEAVING) &&
+                               (proc->reloads > max_reloads) && (proc->pid > 0)) {
+                               kill(proc->pid, SIGTERM);
+                       }
+
+               }
+       }
+       /* stop previous worker process, if it wasn't signaled during max reloads check */
+       list_for_each_entry(proc, &proc_list, list) {
+               if ((proc->options & PROC_O_TYPE_WORKER) &&
+                       (proc->options & PROC_O_LEAVING) &&
+                       (proc->reloads >= 1)) {
+                       kill(proc->pid, oldpids_sig);
+               }
+       }
+
+       return 1;
+}
+
 void pcli_write_prompt(struct stream *s)
 {
        struct buffer *msg = get_trash_chunk();
@@ -3594,6 +3630,7 @@ static struct cli_kw_list cli_kws = {{ },{
        { { "operator", NULL },                  "operator                                : lower the level of the current CLI session to operator",  cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},
        { { "user", NULL },                      "user                                    : lower the level of the current CLI session to user",      cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},
        { { "wait", NULL },                      "wait {-h|<delay_ms>} cond [args...]     : wait the specified delay or condition (-h to see list)",  cli_parse_wait, cli_io_handler_wait, cli_release_wait, NULL },
+       { { "_send_status", NULL },              NULL,                                                                                                _send_status, NULL, NULL, NULL, ACCESS_MASTER_ONLY },
        {{},}
 }};
 
index d163998620cf862058e0db248bc01a15e83d5801..cbbbb3728012579359198c78c6d0ac98c1f6d4a9 100644 (file)
@@ -238,7 +238,7 @@ char *check_condition = NULL; /* check condition passed to -cc */
  */
 #define MAX_START_RETRIES      200
 static int *oldpids = NULL;
-static int oldpids_sig; /* use USR1 or TERM */
+int oldpids_sig; /* use USR1 or TERM */
 
 /* Path to the unix socket we use to retrieve listener sockets from the old process */
 static const char *old_unixsocket;
index 46211c222f975d432b53ef3eb0870c4a6ef9aa35..431935852cc2213f0532d66bda70df305493601f 100644 (file)
@@ -46,7 +46,7 @@
 #endif
 
 static int exitcode = -1;
-static int max_reloads = -1; /* number max of reloads a worker can have until they are killed */
+int max_reloads = INT_MAX; /* max number of reloads a worker can have until they are killed */
 struct mworker_proc *proc_self = NULL; /* process structure of current process */
 struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf); /* master CLI configuration (-S flag) */