#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>
}
+/*
+ * 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 */
#include <common/hathreads.h>
#include <types/capture.h>
+#include <types/cli.h>
#include <types/filters.h>
#include <types/global.h>
#include <types/acl.h>
#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>
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();
/* 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]);
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 */
/* 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);
}