mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 14:21:25 +02:00
MEDIUM: mworker: each worker socketpair is a CLI listener
The init code of the mworker_proc structs has been moved before the init of the listeners. Each socketpair is now connected to a CLI within the workers, which allows the master to access their CLI. The inherited flag of the worker side socketpair is removed so the socket can be closed in the master.
This commit is contained in:
parent
f1a62860c8
commit
ce83b4a5dd
@ -28,5 +28,7 @@ void cli_register_kw(struct cli_kw_list *kw_list);
|
||||
|
||||
int cli_has_level(struct appctx *appctx, int level);
|
||||
|
||||
int mworker_cli_sockpair_new(struct mworker_proc *mworker_proc, int proc);
|
||||
|
||||
#endif /* _PROTO_CLI_H */
|
||||
|
||||
|
58
src/cli.c
58
src/cli.c
@ -56,6 +56,7 @@
|
||||
#include <proto/log.h>
|
||||
#include <proto/pattern.h>
|
||||
#include <proto/pipe.h>
|
||||
#include <proto/protocol.h>
|
||||
#include <proto/listener.h>
|
||||
#include <proto/map.h>
|
||||
#include <proto/proxy.h>
|
||||
@ -1565,6 +1566,63 @@ static int cli_parse_simple(char **args, char *payload, struct appctx *appctx, v
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create a new CLI socket using a socketpair for a worker process
|
||||
* <mworker_proc> is the process structure, and <proc> is the process number
|
||||
*/
|
||||
int mworker_cli_sockpair_new(struct mworker_proc *mworker_proc, int proc)
|
||||
{
|
||||
struct bind_conf *bind_conf;
|
||||
struct listener *l;
|
||||
char *path = NULL;
|
||||
char *err = NULL;
|
||||
|
||||
/* master pipe to ensure the master is still alive */
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, mworker_proc->ipc_fd) < 0) {
|
||||
ha_alert("Cannot create worker socketpair.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX: we might want to use a separate frontend at some point */
|
||||
if (!global.stats_fe) {
|
||||
if ((global.stats_fe = alloc_stats_fe("GLOBAL", "master-socket", 0)) == NULL) {
|
||||
ha_alert("out of memory trying to allocate the stats frontend");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bind_conf = bind_conf_alloc(global.stats_fe, "master-socket", 0, "", xprt_get(XPRT_RAW));
|
||||
bind_conf->level &= ~ACCESS_LVL_MASK;
|
||||
bind_conf->level |= ACCESS_LVL_ADMIN; /* TODO: need to lower the rights with a CLI keyword*/
|
||||
|
||||
bind_conf->bind_proc = 1UL << proc;
|
||||
global.stats_fe->bind_proc = 0; /* XXX: we should be careful with that, it can be removed by configuration */
|
||||
|
||||
if (!memprintf(&path, "sockpair@%d", mworker_proc->ipc_fd[1])) {
|
||||
ha_alert("Cannot allocate listener.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!str2listener(path, global.stats_fe, bind_conf, "master-socket", 0, &err)) {
|
||||
ha_alert("Cannot create a CLI sockpair listener for process #%d\n", proc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_for_each_entry(l, &bind_conf->listeners, by_bind) {
|
||||
l->maxconn = global.stats_fe->maxconn;
|
||||
l->backlog = global.stats_fe->backlog;
|
||||
l->accept = session_accept_fd;
|
||||
l->default_target = global.stats_fe->default_target;
|
||||
l->options |= LI_O_UNLIMITED;
|
||||
/* it's a sockpair but we don't want to keep the fd in the master */
|
||||
l->options &= ~LI_O_INHERITED;
|
||||
l->nice = -64; /* we want to boost priority for local stats */
|
||||
global.maxsock += l->maxconn;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct applet cli_applet = {
|
||||
.obj_type = OBJ_TYPE_APPLET,
|
||||
.name = "<CLI>", /* used for logging */
|
||||
|
@ -84,6 +84,7 @@
|
||||
#include <common/hathreads.h>
|
||||
|
||||
#include <types/capture.h>
|
||||
#include <types/cli.h>
|
||||
#include <types/filters.h>
|
||||
#include <types/global.h>
|
||||
#include <types/acl.h>
|
||||
@ -94,6 +95,7 @@
|
||||
#include <proto/auth.h>
|
||||
#include <proto/backend.h>
|
||||
#include <proto/channel.h>
|
||||
#include <proto/cli.h>
|
||||
#include <proto/connection.h>
|
||||
#include <proto/fd.h>
|
||||
#include <proto/filters.h>
|
||||
@ -1709,6 +1711,30 @@ static void init(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (global.mode & MODE_MWORKER) {
|
||||
int proc;
|
||||
|
||||
for (proc = 0; proc < global.nbproc; proc++) {
|
||||
struct mworker_proc *tmproc;
|
||||
|
||||
tmproc = malloc(sizeof(*tmproc));
|
||||
if (!tmproc) {
|
||||
ha_alert("Cannot allocate process structures.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
tmproc->pid = -1;
|
||||
tmproc->reloads = 0;
|
||||
tmproc->relative_pid = 1 + proc;
|
||||
|
||||
if (mworker_cli_sockpair_new(tmproc, proc) < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LIST_ADDQ(&proc_list, &tmproc->list);
|
||||
}
|
||||
}
|
||||
|
||||
pattern_finalize_config();
|
||||
|
||||
err_code |= check_config_validity();
|
||||
@ -2914,25 +2940,6 @@ int main(int argc, char **argv)
|
||||
|
||||
/* the father launches the required number of processes */
|
||||
for (proc = 0; proc < global.nbproc; proc++) {
|
||||
if (global.mode & MODE_MWORKER) {
|
||||
|
||||
proc_self = malloc(sizeof(*proc_self));
|
||||
if (!proc_self) {
|
||||
ha_alert("[%s.main()] Cannot allocate process structures.\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* master pipe to ensure the master is still alive */
|
||||
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, proc_self->ipc_fd);
|
||||
if (ret < 0) {
|
||||
ha_alert("[%s.main()] Cannot create master pipe.\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
proc_self->reloads = 0;
|
||||
proc_self->relative_pid = relative_pid;
|
||||
LIST_ADDQ(&proc_list, &proc_self->list);
|
||||
}
|
||||
}
|
||||
ret = fork();
|
||||
if (ret < 0) {
|
||||
ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
|
||||
@ -2948,9 +2955,16 @@ int main(int argc, char **argv)
|
||||
shut_your_big_mouth_gcc(write(pidfd, pidstr, strlen(pidstr)));
|
||||
}
|
||||
if (global.mode & MODE_MWORKER) {
|
||||
proc_self->pid = ret;
|
||||
close(proc_self->ipc_fd[1]); /* close client side */
|
||||
proc_self->ipc_fd[1] = -1;
|
||||
struct mworker_proc *child;
|
||||
|
||||
/* find the right mworker_proc */
|
||||
list_for_each_entry(child, &proc_list, list) {
|
||||
if (child->relative_pid == relative_pid &&
|
||||
child->reloads == 0) {
|
||||
child->pid = ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
relative_pid++; /* each child will get a different one */
|
||||
@ -3020,13 +3034,17 @@ int main(int argc, char **argv)
|
||||
|
||||
/* free proc struct of other processes */
|
||||
list_for_each_entry_safe(child, it, &proc_list, list) {
|
||||
if (child->ipc_fd[0] > -1) {
|
||||
close(child->ipc_fd[0]);
|
||||
child->ipc_fd[0] = -1;
|
||||
}
|
||||
if (child == proc_self)
|
||||
/* close the FD of the master side for all
|
||||
* workers, we don't need to close the worker
|
||||
* side of other workers since it's done with
|
||||
* the bind_proc */
|
||||
close(child->ipc_fd[0]);
|
||||
if (child->relative_pid == relative_pid &&
|
||||
child->reloads == 0) {
|
||||
/* keep this struct if this is our pid */
|
||||
proc_self = child;
|
||||
continue;
|
||||
close(child->ipc_fd[1]);
|
||||
}
|
||||
LIST_DEL(&child->list);
|
||||
free(child);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user