MINOR: mworker/cli: add _send_status to support state transition

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.
This commit is contained in:
Valentine Krasnobaeva 2024-10-02 14:48:01 +02:00 committed by Willy Tarreau
parent 154848a314
commit b73a278df4
5 changed files with 41 additions and 2 deletions

View 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;

View 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;

View File

@ -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 },
{{},}
}};

View 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;

View 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) */