diff --git a/Makefile b/Makefile index 9f5d3ffed..ba3fd26f3 100644 --- a/Makefile +++ b/Makefile @@ -982,7 +982,7 @@ OBJS += src/mux_h2.o src/mux_h1.o src/mux_fcgi.o src/log.o \ src/cfgcond.o src/proto_udp.o src/lb_fwlc.o src/ebmbtree.o \ src/proto_uxdg.o src/cfgdiag.o src/sock_unix.o src/sha1.o \ src/lb_fas.o src/clock.o src/sock_inet.o src/ev_select.o \ - src/lb_map.o src/shctx.o src/mworker-prog.o src/hpack-dec.o \ + src/lb_map.o src/shctx.o src/hpack-dec.o \ src/arg.o src/signal.o src/fix.o src/dynbuf.o src/guid.o \ src/cfgparse-tcp.o src/lb_ss.o src/chunk.o src/counters.o \ src/cfgparse-unix.o src/regex.o src/fcgi.o src/uri_auth.o \ diff --git a/include/haproxy/mworker-t.h b/include/haproxy/mworker-t.h index 46e125f36..52f6573f2 100644 --- a/include/haproxy/mworker-t.h +++ b/include/haproxy/mworker-t.h @@ -21,7 +21,7 @@ #define PROC_O_TYPE_MASTER 0x00000001 #define PROC_O_TYPE_WORKER 0x00000002 -#define PROC_O_TYPE_PROG 0x00000004 +/* 0x00000004 unused */ /* 0x00000008 unused */ #define PROC_O_LEAVING 0x00000010 /* this process should be leaving */ /* state of the newly forked worker process, which hasn't sent yet its READY message to master */ diff --git a/include/haproxy/mworker.h b/include/haproxy/mworker.h index 57d62643d..6924650ec 100644 --- a/include/haproxy/mworker.h +++ b/include/haproxy/mworker.h @@ -42,8 +42,6 @@ void mworker_cleanlisteners(void); int mworker_child_nb(void); -int mworker_ext_launch_all(void); - void mworker_kill_max_reloads(int sig); struct mworker_proc *mworker_proc_new(); diff --git a/reg-tests/mcli/mcli_start_progs.vtc b/reg-tests/mcli/mcli_start_progs.vtc deleted file mode 100644 index 5b5549aa6..000000000 --- a/reg-tests/mcli/mcli_start_progs.vtc +++ /dev/null @@ -1,40 +0,0 @@ -#EXCLUDE_TARGETS=osx -varnishtest "Try to start a master CLI with 2 programs" -#REGTEST_TYPE=bug -feature cmd "command -v sleep" - -feature ignore_unknown_macro - -# Do nothing. Is there only to create s1_* macros -server s1 { -} -start - -haproxy h1 -Ws -S -conf { - global - expose-deprecated-directives - defaults - mode http - timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" - timeout client "${HAPROXY_TEST_TIMEOUT-5s}" - timeout server "${HAPROXY_TEST_TIMEOUT-5s}" - - frontend myfrontend - bind "fd@${my_fe}" - default_backend test - - backend test - server www1 ${s1_addr}:${s1_port} - - program foo - command sleep 10 - - program bar - command sleep 10 - -} -start - -haproxy h1 -mcli { - delay 0.1 - send "show proc" - expect ~ ".*foo.*\n.*bar.*\n" -} -wait diff --git a/src/haproxy.c b/src/haproxy.c index 2802a36cf..731442eb6 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2561,7 +2561,6 @@ static void run_master_in_recovery_mode(int argc, char **argv) static void read_cfg_in_discovery_mode(int argc, char **argv) { struct cfgfile *cfg, *cfg_tmp; - struct mworker_proc *proc; /* load configs in memory and parse only global section (MODE_DISCOVERY) */ global.mode |= MODE_DISCOVERY; @@ -2611,36 +2610,6 @@ static void read_cfg_in_discovery_mode(int argc, char **argv) exit(EXIT_FAILURE); } - /* "program" sections, if there are any, were already parsed only by master - * and programs are forked before calling postparser functions from - * postparser list. So, all checks related to "program" section integrity - * and sections vs MODE_MWORKER combinations should be done here. - */ - list_for_each_entry(proc, &proc_list, list) { - if (proc->options & PROC_O_TYPE_PROG) { - if (!(global.mode & MODE_MWORKER)) { - ha_alert("'program' section is defined in configuration, " - "but master-worker mode (-W) is not enabled.\n"); - exit(EXIT_FAILURE); - } - - if ((proc->reloads == 0) && (proc->command == NULL)) { - if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) { - ha_warning("Master failed to parse new configuration: " - "the program section '%s' lacks a command to launch. " - "It can't start a new worker and launch defined programs. " - "Already running worker and programs " - "will be kept. Please, check program section settings\n", proc->id); - - run_master_in_recovery_mode(argc, argv); - } else { - ha_alert("The program section '%s' lacks a command to launch.\n", proc->id); - exit(EXIT_FAILURE); - } - } - } - } - /* in MODE_CHECK and in MODE_DUMP_CFG we just need to parse the * configuration and exit, see step_init_2() */ @@ -3275,8 +3244,6 @@ int main(int argc, char **argv) /* Master-worker and program forks */ if (global.mode & MODE_MWORKER) { - /* fork and run binary from command keyword in program section */ - mworker_ext_launch_all(); /* fork worker */ mworker_apply_master_worker_mode(); } diff --git a/src/mworker-prog.c b/src/mworker-prog.c deleted file mode 100644 index 6aa9ec8ce..000000000 --- a/src/mworker-prog.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Master Worker - program - * - * Copyright HAProxy Technologies - William Lallemand - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - - -static int use_program = 0; /* do we use the program section ? */ - -/* - * Launch every programs - */ -int mworker_ext_launch_all() -{ - int ret; - struct mworker_proc *child; - struct mworker_proc *tmp; - int reexec = 0; - - if (!use_program) - return 0; - - reexec = getenv("HAPROXY_MWORKER_REEXEC") ? 1 : 0; - - /* find the right mworker_proc */ - list_for_each_entry_safe(child, tmp, &proc_list, list) { - /* need to stop progs, which were launched before reload */ - if ((child->options & PROC_O_TYPE_PROG) && (child->options & PROC_O_LEAVING)) - kill(child->pid, oldpids_sig); - - if (child->reloads == 0 && (child->options & PROC_O_TYPE_PROG)) { - - if (reexec && (!(child->options & PROC_O_START_RELOAD))) { - struct mworker_proc *old_child; - - /* - * This is a reload and we don't want to fork a - * new program so have to remove the entry in - * the list. - * - * But before that, we need to mark the - * previous program as not leaving, if we find one. - */ - - list_for_each_entry(old_child, &proc_list, list) { - if (!(old_child->options & PROC_O_TYPE_PROG) || (!(old_child->options & PROC_O_LEAVING))) - continue; - - if (strcmp(old_child->id, child->id) == 0) - old_child->options &= ~PROC_O_LEAVING; - } - - - LIST_DELETE(&child->list); - mworker_free_child(child); - child = NULL; - - continue; - } - - child->timestamp = ns_to_sec(now_ns); - - ret = fork(); - if (ret < 0) { - ha_alert("Cannot fork program '%s'.\n", child->id); - exit(EXIT_FAILURE); /* there has been an error */ - } else if (ret > 0) { /* parent */ - child->pid = ret; - ha_notice("New program '%s' (%d) forked\n", child->id, ret); - continue; - } else if (ret == 0) { - /* In child */ - mworker_unblock_signals(); - mworker_cleanlisteners(); - mworker_cleantasks(); - - /* setgid / setuid */ - if (child->gid != -1) { - if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1) - ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'" - " without 'uid'/'user' is generally useless.\n", child->command[0]); - - if (setgid(child->gid) == -1) { - ha_alert("[%s.main()] Cannot set gid %d.\n", child->command[0], child->gid); - exit(1); - } - } - - if (child->uid != -1 && setuid(child->uid) == -1) { - ha_alert("[%s.main()] Cannot set uid %d.\n", child->command[0], child->gid); - exit(1); - } - - /* This one must not be exported, it's internal! */ - unsetenv("HAPROXY_MWORKER_REEXEC"); - unsetenv("HAPROXY_PROCESSES"); - execvp(child->command[0], child->command); - - ha_alert("Cannot execute %s: %s\n", child->command[0], strerror(errno)); - exit(EXIT_FAILURE); - } - } - } - - return 0; - -} - - -/* Configuration */ - -int cfg_parse_program(const char *file, int linenum, char **args, int kwm) -{ - static struct mworker_proc *ext_child = NULL; - struct mworker_proc *child; - int err_code = 0; - - if (!(global.mode & MODE_DISCOVERY)) - return err_code; - - if (strcmp(args[0], "program") == 0) { - if (alertif_too_many_args(1, file, linenum, args, &err_code)) { - err_code |= ERR_ABORT; - goto error; - } - - if (!*args[1]) { - ha_alert("parsing [%s:%d] : '%s' expects an argument\n", - file, linenum, args[0]); - err_code |= ERR_ALERT | ERR_ABORT; - goto error; - } - - ext_child = calloc(1, sizeof(*ext_child)); - if (!ext_child) { - ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); - err_code |= ERR_ALERT | ERR_ABORT; - goto error; - } - - ext_child->options |= PROC_O_TYPE_PROG; /* external process */ - ext_child->command = NULL; - ext_child->path = NULL; - ext_child->id = NULL; - ext_child->pid = -1; - ext_child->reloads = 0; - ext_child->timestamp = -1; - ext_child->ipc_fd[0] = -1; - ext_child->ipc_fd[1] = -1; - ext_child->options |= PROC_O_START_RELOAD; /* restart the programs by default */ - ext_child->uid = -1; - ext_child->gid = -1; - LIST_INIT(&ext_child->list); - - list_for_each_entry(child, &proc_list, list) { - if (child->reloads == 0 && (child->options & PROC_O_TYPE_PROG)) { - if (strcmp(args[1], child->id) == 0) { - ha_alert("parsing [%s:%d]: '%s' program section already exists in the configuration.\n", file, linenum, args[1]); - err_code |= ERR_ALERT | ERR_ABORT; - goto error; - } - } - } - - ext_child->id = strdup(args[1]); - if (!ext_child->id) { - ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); - err_code |= ERR_ALERT | ERR_ABORT; - goto error; - } - - if (!deprecated_directives_allowed) { - ha_warning("parsing [%s:%d]: The 'program' section is deprecated and will be eventually removed, " - "it can be still allowed by setting 'expose-deprecated-directives' keyword in the 'global' " - "section defined before any 'program' section. Please, consider to use a process manager instead " - "of 'program' section, such as sysvinit, systemd, supervisord or s6.\n", - file, linenum); - err_code |= ERR_ALERT | ERR_ABORT; - goto error; - } - - LIST_APPEND(&proc_list, &ext_child->list); - - } else if (strcmp(args[0], "command") == 0) { - int arg_nb = 0; - int i = 0; - - if (*(args[1]) == 0) { - ha_alert("parsing [%s:%d]: '%s' expects a command with optional arguments separated in words.\n", file, linenum, args[0]); - err_code |= ERR_ALERT | ERR_FATAL; - goto error; - } - - while (*args[arg_nb+1]) - arg_nb++; - - ext_child->command = calloc(arg_nb+1, sizeof(*ext_child->command)); - - if (!ext_child->command) { - ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); - err_code |= ERR_ALERT | ERR_ABORT; - goto error; - } - - while (i < arg_nb) { - ext_child->command[i] = strdup(args[i+1]); - if (!ext_child->command[i]) { - ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); - err_code |= ERR_ALERT | ERR_ABORT; - goto error; - } - i++; - } - ext_child->command[i] = NULL; - - } else if (strcmp(args[0], "option") == 0) { - - if (*(args[1]) == '\0') { - ha_alert("parsing [%s:%d]: '%s' expects an option name.\n", - file, linenum, args[0]); - err_code |= ERR_ALERT | ERR_FATAL; - goto error; - } - - if (strcmp(args[1], "start-on-reload") == 0) { - if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code)) - goto error; - if (kwm == KWM_STD) - ext_child->options |= PROC_O_START_RELOAD; - else if (kwm == KWM_NO) - ext_child->options &= ~PROC_O_START_RELOAD; - goto out; - - } else { - ha_alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]); - err_code |= ERR_ALERT | ERR_FATAL; - goto error; - } - } else if (strcmp(args[0], "user") == 0) { - struct passwd *ext_child_user; - if (*(args[1]) == '\0') { - ha_alert("parsing [%s:%d]: '%s' expects a user name.\n", - file, linenum, args[0]); - err_code |= ERR_ALERT | ERR_FATAL; - goto error; - } - - if (alertif_too_many_args(1, file, linenum, args, &err_code)) - goto error; - - if (ext_child->uid != -1) { - ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum); - err_code |= ERR_ALERT; - goto out; - } - - ext_child_user = getpwnam(args[1]); - if (ext_child_user != NULL) { - ext_child->uid = (int)ext_child_user->pw_uid; - } else { - ha_alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno)); - err_code |= ERR_ALERT | ERR_FATAL; - } - } else if (strcmp(args[0], "group") == 0) { - struct group *ext_child_group; - if (*(args[1]) == '\0') { - ha_alert("parsing [%s:%d]: '%s' expects a group name.\n", - file, linenum, args[0]); - err_code |= ERR_ALERT | ERR_FATAL; - goto error; - } - - if (alertif_too_many_args(1, file, linenum, args, &err_code)) - goto error; - - if (ext_child->gid != -1) { - ha_alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum); - err_code |= ERR_ALERT; - goto out; - } - - ext_child_group = getgrnam(args[1]); - if (ext_child_group != NULL) { - ext_child->gid = (int)ext_child_group->gr_gid; - } else { - ha_alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno)); - err_code |= ERR_ALERT | ERR_FATAL; - } - } else { - ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "program"); - err_code |= ERR_ALERT | ERR_FATAL; - goto error; - } - - use_program = 1; - - return err_code; - -error: - if (ext_child) { - LIST_DELETE(&ext_child->list); - if (ext_child->command) { - int i; - - for (i = 0; ext_child->command[i]; i++) { - ha_free(&ext_child->command[i]); - } - ha_free(&ext_child->command); - } - ha_free(&ext_child->id); - } - - ha_free(&ext_child); - -out: - return err_code; - -} - -REGISTER_CONFIG_SECTION("program", cfg_parse_program, NULL); diff --git a/src/mworker.c b/src/mworker.c index f491ae6d7..88bcc1f05 100644 --- a/src/mworker.c +++ b/src/mworker.c @@ -62,7 +62,7 @@ static void mworker_kill(int sig) list_for_each_entry(child, &proc_list, list) { /* careful there, we must be sure that the pid > 0, we don't want to emit a kill -1 */ - if ((child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) && (child->pid > 0)) + if ((child->options & PROC_O_TYPE_WORKER) && (child->pid > 0)) kill(child->pid, sig); } } @@ -84,7 +84,7 @@ int mworker_current_child(int pid) struct mworker_proc *child; list_for_each_entry(child, &proc_list, list) { - if ((child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) && (!(child->options & PROC_O_LEAVING)) && (child->pid == pid)) + if ((child->options & PROC_O_TYPE_WORKER) && (!(child->options & PROC_O_LEAVING)) && (child->pid == pid)) return 1; } return 0; @@ -100,7 +100,7 @@ int mworker_child_nb() int ret = 0; list_for_each_entry(child, &proc_list, list) { - if (child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) + if (child->options & PROC_O_TYPE_WORKER) ret++; } @@ -121,8 +121,6 @@ void mworker_proc_list_to_env() if (child->options & PROC_O_TYPE_MASTER) type = 'm'; - else if (child->options & PROC_O_TYPE_PROG) - type = 'e'; else if (child->options &= PROC_O_TYPE_WORKER) type = 'w'; @@ -197,8 +195,6 @@ int mworker_env_to_proc_list() if (type == 'm') { /* we are in the master, assign it */ proc_self = child; child->options |= PROC_O_TYPE_MASTER; - } else if (type == 'e') { - child->options |= PROC_O_TYPE_PROG; } else if (type == 'w') { child->options |= PROC_O_TYPE_WORKER; } @@ -594,8 +590,6 @@ void mworker_catch_sigchld(struct sig_handler *sh) else ha_alert("Current worker (%d) exited with code %d (%s)\n", exitpid, status, strsignal(status - 128)); } - else if (child->options & PROC_O_TYPE_PROG) - ha_alert("Current program '%s' (%d) exited with code %d (%s)\n", child->id, exitpid, status, (status >= 128) ? strsignal(status - 128) : "Exit"); if (status != 0 && status != 130 && status != 143) { if (child->options & PROC_O_TYPE_WORKER) { @@ -620,11 +614,6 @@ void mworker_catch_sigchld(struct sig_handler *sh) /* Delete fd from poller fdtab, which will close it */ fd_delete(child->ipc_fd[0]); delete_oldpid(exitpid); - } else if (child->options & PROC_O_TYPE_PROG) { - /* ipc_fd[0] and ipc_fd[1] are not used for PROC_O_TYPE_PROG and kept as -1, - * thus they are never inserted in fdtab (otherwise, BUG_ON in fd_insert if fd <0) - */ - ha_warning("Former program '%s' (%d) exited with code %d (%s)\n", child->id, exitpid, status, (status >= 128) ? strsignal(status - 128) : "Exit"); } } mworker_free_child(child); @@ -796,7 +785,6 @@ static int cli_io_handler_show_proc(struct appctx *appctx) struct cli_showproc_ctx *ctx = appctx->svcctx; char *uptime = NULL; char *reloadtxt = NULL; - int program_nb = 0; if (up < 0) /* must never be negative because of clock drift */ up = 0; @@ -865,48 +853,6 @@ static int cli_io_handler_show_proc(struct appctx *appctx) free(msg); } - /* displays external process */ - old = 0; - list_for_each_entry(child, &proc_list, list) { - up = date.tv_sec - child->timestamp; - if (up < 0) /* must never be negative because of clock drift */ - up = 0; - - if (!(child->options & PROC_O_TYPE_PROG)) - continue; - - if (child->options & PROC_O_LEAVING) { - old++; - continue; - } - if (program_nb == 0) - chunk_appendf(&trash, "# programs\n"); - program_nb++; - memprintf(&uptime, "%dd%02dh%02dm%02ds", up / 86400, (up % 86400) / 3600, (up % 3600) / 60, (up % 60)); - chunk_appendf(&trash, "%-15u %-15s %-15d %-15s %-15s\n", child->pid, child->id, child->reloads, uptime, "-"); - ha_free(&uptime); - } - - if (old) { - chunk_appendf(&trash, "# old programs\n"); - list_for_each_entry(child, &proc_list, list) { - up = date.tv_sec - child->timestamp; - if (up < 0) /* must never be negative because of clock drift */ - up = 0; - - if (!(child->options & PROC_O_TYPE_PROG)) - continue; - - if (child->options & PROC_O_LEAVING) { - memprintf(&uptime, "%dd%02dh%02dm%02ds", up / 86400, (up % 86400) / 3600, (up % 3600) / 60, (up % 60)); - chunk_appendf(&trash, "%-15u %-15s %-15d %-15s %-15s\n", child->pid, child->id, child->reloads, uptime, "-"); - ha_free(&uptime); - } - } - } - - - if (applet_putchk(appctx, &trash) == -1) return 0;