From: William Lallemand Date: Mon, 1 Apr 2019 09:29:56 +0000 (+0200) Subject: REORG: mworker: move signal handlers and related functions X-Git-Tag: v2.0-dev3~350 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e25473c846078c374a5766599265c7d84eb0f4b8;p=thirdparty%2Fhaproxy.git 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 25d8c8c7f7..becb123a1d 100644 --- a/include/proto/mworker.h +++ b/include/proto/mworker.h @@ -13,6 +13,8 @@ #ifndef PROTO_MWORKER_H_ #define PROTO_MWORKER_H_ +#include + void mworker_proc_list_to_env(); void mworker_env_to_proc_list(); @@ -20,7 +22,13 @@ void mworker_env_to_proc_list(); 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 009814bcbb..6b06e7f0f5 100644 --- a/include/types/global.h +++ b/include/types/global.h @@ -224,6 +224,7 @@ extern struct mworker_proc *proc_self; /* process structure of current process * 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 @@ static inline unsigned long thread_mask(unsigned long mask) 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 f3209de9ce..52bf2be836 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -202,8 +202,6 @@ static char *cur_unixsocket = NULL; int atexit_flag = 0; -static int exitcode = -1; - int nb_oldpids = 0; const int zero = 0; const int one = 1; @@ -217,8 +215,6 @@ char localpeer[MAX_HOSTNAME_LEN]; */ 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 @@ static void usage(char *name) /* sends the signal to all pids found in . 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 @@ static int tell_old_pids(int sig) 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 @@ alloc_error: 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 2631764986..786cc44e74 100644 --- a/src/mworker.c +++ b/src/mworker.c @@ -15,16 +15,57 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include +#if defined(USE_SYSTEMD) +#include +#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 @@ -111,6 +152,101 @@ void mworker_unblock_signals() 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