REORG: mworker: move signal handlers and related functions
Move the following functions to mworker.c:
void mworker_catch_sighup(struct sig_handler *sh);
void mworker_catch_sigterm(struct sig_handler *sh);
void mworker_catch_sigchld(struct sig_handler *sh);
static void mworker_kill(int sig);
int current_child(int pid);
diff --git a/include/proto/mworker.h b/include/proto/mworker.h
index 25d8c8c..becb123 100644
--- a/include/proto/mworker.h
+++ b/include/proto/mworker.h
@@ -13,6 +13,8 @@
#ifndef PROTO_MWORKER_H_
#define PROTO_MWORKER_H_
+#include <types/signal.h>
+
void mworker_proc_list_to_env();
void mworker_env_to_proc_list();
@@ -20,7 +22,13 @@
void mworker_block_signals();
void mworker_unblock_signals();
+void mworker_catch_sighup(struct sig_handler *sh);
+void mworker_catch_sigterm(struct sig_handler *sh);
+void mworker_catch_sigchld(struct sig_handler *sh);
+
void mworker_accept_wrapper(int fd);
void mworker_pipe_register();
+extern int *children; /* store PIDs of children in master workers mode */
+
#endif /* PROTO_MWORKER_H_ */
diff --git a/include/types/global.h b/include/types/global.h
index 009814b..6b06e7f 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -224,6 +224,7 @@
extern int master; /* 1 if in master, 0 otherwise */
extern unsigned int rlim_fd_cur_at_boot;
extern unsigned int rlim_fd_max_at_boot;
+extern int atexit_flag;
/* bit values to go with "warned" above */
#define WARN_BLOCK_DEPRECATED 0x00000001
@@ -254,6 +255,9 @@
return mask ? mask : all_threads_mask;
}
+int tell_old_pids(int sig);
+int delete_oldpid(int pid);
+
void deinit(void);
void hap_register_build_opts(const char *str, int must_free);
void hap_register_post_check(int (*fct)());
diff --git a/src/haproxy.c b/src/haproxy.c
index f3209de..52bf2be 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -202,8 +202,6 @@
int atexit_flag = 0;
-static int exitcode = -1;
-
int nb_oldpids = 0;
const int zero = 0;
const int one = 1;
@@ -217,8 +215,6 @@
*/
int shut_your_big_mouth_gcc_int = 0;
-int *children = NULL; /* store PIDs of children in master workers mode */
-
static char **next_argv = NULL;
struct list proc_list = LIST_HEAD_INIT(proc_list);
@@ -488,7 +484,7 @@
/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
* pids the signal was correctly delivered to.
*/
-static int tell_old_pids(int sig)
+int tell_old_pids(int sig)
{
int p;
int ret = 0;
@@ -498,34 +494,6 @@
return ret;
}
-/* return 1 if a pid is a current child otherwise 0 */
-
-int current_child(int pid)
-{
- int i;
-
- for (i = 0; i < global.nbproc; i++) {
- if (children[i] == pid)
- return 1;
- }
- return 0;
-}
-
-/*
- * Send signal to every known children.
- */
-
-static void mworker_kill(int sig)
-{
- int i;
-
- tell_old_pids(sig);
- if (children) {
- for (i = 0; i < global.nbproc; i++)
- kill(children[i], sig);
- }
-}
-
/*
* Upon a reload, the master worker needs to close all listeners FDs but the mworker_pipe
@@ -726,98 +694,6 @@
return;
}
-/*
- * When called, this function reexec haproxy with -sf followed by current
- * children PIDs and possibly old children PIDs if they didn't leave yet.
- */
-static void mworker_catch_sighup(struct sig_handler *sh)
-{
- mworker_reload();
-}
-
-static void mworker_catch_sigterm(struct sig_handler *sh)
-{
- int sig = sh->arg;
-
-#if defined(USE_SYSTEMD)
- if (global.tune.options & GTUNE_USE_SYSTEMD) {
- sd_notify(0, "STOPPING=1");
- }
-#endif
- ha_warning("Exiting Master process...\n");
- mworker_kill(sig);
-}
-
-/*
- * Wait for every children to exit
- */
-
-static void mworker_catch_sigchld(struct sig_handler *sh)
-{
- int exitpid = -1;
- int status = 0;
- struct mworker_proc *child, *it;
- int childfound;
-
-restart_wait:
-
- childfound = 0;
-
- exitpid = waitpid(-1, &status, WNOHANG);
- if (exitpid > 0) {
- if (WIFEXITED(status))
- status = WEXITSTATUS(status);
- else if (WIFSIGNALED(status))
- status = 128 + WTERMSIG(status);
- else if (WIFSTOPPED(status))
- status = 128 + WSTOPSIG(status);
- else
- status = 255;
-
- list_for_each_entry_safe(child, it, &proc_list, list) {
- if (child->pid != exitpid)
- continue;
-
- LIST_DEL(&child->list);
- close(child->ipc_fd[0]);
- childfound = 1;
- break;
- }
-
- if (!children || !childfound) {
- ha_warning("Worker %d exited with code %d (%s)\n", exitpid, status, (status >= 128) ? strsignal(status - 128) : "Exit");
- } else {
- /* check if exited child was in the current children list */
- if (current_child(exitpid)) {
- ha_alert("Current worker #%d (%d) exited with code %d (%s)\n", child->relative_pid, exitpid, status, (status >= 128) ? strsignal(status - 128) : "Exit");
- if (status != 0 && status != 130 && status != 143
- && !(global.tune.options & GTUNE_NOEXIT_ONFAILURE)) {
- ha_alert("exit-on-failure: killing every workers with SIGTERM\n");
- if (exitcode < 0)
- exitcode = status;
- mworker_kill(SIGTERM);
- }
- } else {
- ha_warning("Former worker #%d (%d) exited with code %d (%s)\n", child->relative_pid, exitpid, status, (status >= 128) ? strsignal(status - 128) : "Exit");
- delete_oldpid(exitpid);
- }
- free(child);
- }
-
- /* do it again to check if it was the last worker */
- goto restart_wait;
- }
- /* Better rely on the system than on a list of process to check if it was the last one */
- else if (exitpid == -1 && errno == ECHILD) {
- ha_warning("All workers exited. Exiting... (%d)\n", (exitcode > 0) ? exitcode : status);
- atexit_flag = 0;
- if (exitcode > 0)
- exit(exitcode);
- exit(status); /* parent must leave using the latest status code known */
- }
-
-}
-
static void mworker_loop()
{
diff --git a/src/mworker.c b/src/mworker.c
index 2631764..786cc44 100644
--- a/src/mworker.c
+++ b/src/mworker.c
@@ -15,18 +15,59 @@
#include <signal.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/wait.h>
#include <common/mini-clist.h>
#include <proto/fd.h>
#include <proto/listener.h>
+#include <proto/log.h>
#include <proto/mworker.h>
#include <proto/signal.h>
#include <types/global.h>
+#include <types/signal.h>
+#if defined(USE_SYSTEMD)
+#include <systemd/sd-daemon.h>
+#endif
+
+static int exitcode = -1;
+
+int *children = NULL; /* store PIDs of children in master workers mode */
+
+/* ----- children processes handling ----- */
/*
+ * Send signal to every known children.
+ */
+
+static void mworker_kill(int sig)
+{
+ int i;
+
+ /* TODO: merge mworker_kill and tell_old_pids for mworker mode */
+ tell_old_pids(sig);
+ if (children) {
+ for (i = 0; i < global.nbproc; i++)
+ kill(children[i], sig);
+ }
+}
+
+
+/* return 1 if a pid is a current child otherwise 0 */
+int current_child(int pid)
+{
+ int i;
+
+ for (i = 0; i < global.nbproc; i++) {
+ if (children[i] == pid)
+ return 1;
+ }
+ return 0;
+}
+
+/*
* serialize the proc list and put it in the environment
*/
void mworker_proc_list_to_env()
@@ -111,6 +152,101 @@
haproxy_unblock_signals();
}
+/* ----- mworker signal handlers ----- */
+
+/*
+ * When called, this function reexec haproxy with -sf followed by current
+ * children PIDs and possibly old children PIDs if they didn't leave yet.
+ */
+void mworker_catch_sighup(struct sig_handler *sh)
+{
+ mworker_reload();
+}
+
+void mworker_catch_sigterm(struct sig_handler *sh)
+{
+ int sig = sh->arg;
+
+#if defined(USE_SYSTEMD)
+ if (global.tune.options & GTUNE_USE_SYSTEMD) {
+ sd_notify(0, "STOPPING=1");
+ }
+#endif
+ ha_warning("Exiting Master process...\n");
+ mworker_kill(sig);
+}
+
+/*
+ * Wait for every children to exit
+ */
+
+void mworker_catch_sigchld(struct sig_handler *sh)
+{
+ int exitpid = -1;
+ int status = 0;
+ struct mworker_proc *child, *it;
+ int childfound;
+
+restart_wait:
+
+ childfound = 0;
+
+ exitpid = waitpid(-1, &status, WNOHANG);
+ if (exitpid > 0) {
+ if (WIFEXITED(status))
+ status = WEXITSTATUS(status);
+ else if (WIFSIGNALED(status))
+ status = 128 + WTERMSIG(status);
+ else if (WIFSTOPPED(status))
+ status = 128 + WSTOPSIG(status);
+ else
+ status = 255;
+
+ list_for_each_entry_safe(child, it, &proc_list, list) {
+ if (child->pid != exitpid)
+ continue;
+
+ LIST_DEL(&child->list);
+ close(child->ipc_fd[0]);
+ childfound = 1;
+ break;
+ }
+
+ if (!children || !childfound) {
+ ha_warning("Worker %d exited with code %d (%s)\n", exitpid, status, (status >= 128) ? strsignal(status - 128) : "Exit");
+ } else {
+ /* check if exited child was in the current children list */
+ if (current_child(exitpid)) {
+ ha_alert("Current worker #%d (%d) exited with code %d (%s)\n", child->relative_pid, exitpid, status, (status >= 128) ? strsignal(status - 128) : "Exit");
+ if (status != 0 && status != 130 && status != 143
+ && !(global.tune.options & GTUNE_NOEXIT_ONFAILURE)) {
+ ha_alert("exit-on-failure: killing every workers with SIGTERM\n");
+ if (exitcode < 0)
+ exitcode = status;
+ mworker_kill(SIGTERM);
+ }
+ } else {
+ ha_warning("Former worker #%d (%d) exited with code %d (%s)\n", child->relative_pid, exitpid, status, (status >= 128) ? strsignal(status - 128) : "Exit");
+ /* TODO: merge children and oldpids list in mworker mode */
+ delete_oldpid(exitpid);
+ }
+ free(child);
+ }
+
+ /* do it again to check if it was the last worker */
+ goto restart_wait;
+ }
+ /* Better rely on the system than on a list of process to check if it was the last one */
+ else if (exitpid == -1 && errno == ECHILD) {
+ ha_warning("All workers exited. Exiting... (%d)\n", (exitcode > 0) ? exitcode : status);
+ atexit_flag = 0;
+ if (exitcode > 0)
+ exit(exitcode);
+ exit(status); /* parent must leave using the latest status code known */
+ }
+
+}
+
/* ----- IPC FD (sockpair) related ----- */
/* This wrapper is called from the workers. It is registered instead of the