mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-05-04 16:57:58 +00:00
MEDIUM: mworker: use the haproxy poll loop
In order to reorganize the code of the master worker, the mworker_wait() function which was the main function was split. This function was handling a wait() loop, but it does not need it anymore since the code will use the poll loop of haproxy instead. The function was split in several functions: - mworker_catch_sigterm() which is a signal handler for SIGTERM ans SIGUSR1 that sends the signals to the workers - mworker_catch_sigchld() which is the code handling the leaving of a child - mworker_catch_sighup which basically call the mworker_restart() function - mworker_loop() which is the function calling the main poll loop in the master
This commit is contained in:
parent
73e1dfcfdf
commit
b3f2be338b
111
src/haproxy.c
111
src/haproxy.c
@ -213,6 +213,8 @@ struct list global_listener_queue = LIST_HEAD_INIT(global_listener_queue);
|
||||
struct task *global_listener_queue_task;
|
||||
static struct task *manage_global_listener_queue(struct task *t, void *context, unsigned short state);
|
||||
|
||||
static void *run_thread_poll_loop(void *data);
|
||||
|
||||
/* bitfield of a few warnings to emit just once (WARN_*) */
|
||||
unsigned int warned = 0;
|
||||
|
||||
@ -481,11 +483,6 @@ int current_child(int pid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mworker_signalhandler(int signum)
|
||||
{
|
||||
caught_signal = signum;
|
||||
}
|
||||
|
||||
static void mworker_block_signals()
|
||||
{
|
||||
sigset_t set;
|
||||
@ -681,6 +678,8 @@ static void mworker_reload()
|
||||
next_argv[next_argc++] = NULL;
|
||||
}
|
||||
|
||||
deinit_pollers(); /* we don't want to leak the poller fd */
|
||||
|
||||
ha_warning("Reexecuting Master process\n");
|
||||
execvp(next_argv[0], next_argv);
|
||||
|
||||
@ -692,51 +691,41 @@ alloc_error:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* When called, this function reexec haproxy with -sf followed by current
|
||||
* children PIDs and possibily 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_wait()
|
||||
static void mworker_catch_sigchld(struct sig_handler *sh)
|
||||
{
|
||||
int exitpid = -1;
|
||||
int status = 0;
|
||||
|
||||
restart_wait:
|
||||
|
||||
#if defined(USE_SYSTEMD)
|
||||
if (global.tune.options & GTUNE_USE_SYSTEMD)
|
||||
sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
|
||||
#endif
|
||||
|
||||
mworker_unblock_signals();
|
||||
|
||||
while (1) {
|
||||
|
||||
while (((exitpid = wait(&status)) == -1) && errno == EINTR) {
|
||||
int sig = caught_signal;
|
||||
if (sig == SIGUSR2 || sig == SIGHUP) {
|
||||
mworker_reload();
|
||||
/* should reach there only if it fail */
|
||||
goto restart_wait;
|
||||
} else {
|
||||
#if defined(USE_SYSTEMD)
|
||||
if ((global.tune.options & GTUNE_USE_SYSTEMD) && (sig == SIGUSR1 || sig == SIGTERM)) {
|
||||
sd_notify(0, "STOPPING=1");
|
||||
}
|
||||
#endif
|
||||
ha_warning("Exiting Master process...\n");
|
||||
mworker_kill(sig);
|
||||
}
|
||||
caught_signal = 0;
|
||||
}
|
||||
|
||||
if (exitpid == -1 && errno == ECHILD) {
|
||||
ha_warning("All workers exited. Exiting... (%d)\n", status);
|
||||
atexit_flag = 0;
|
||||
exit(status); /* parent must leave using the latest status code known */
|
||||
}
|
||||
|
||||
exitpid = waitpid(-1, &status, WNOHANG);
|
||||
if (exitpid > 0) {
|
||||
if (WIFEXITED(status))
|
||||
status = WEXITSTATUS(status);
|
||||
else if (WIFSIGNALED(status))
|
||||
@ -762,9 +751,47 @@ restart_wait:
|
||||
delete_oldpid(exitpid);
|
||||
}
|
||||
}
|
||||
/* 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", status);
|
||||
atexit_flag = 0;
|
||||
exit(status); /* parent must leave using the latest status code known */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void mworker_loop()
|
||||
{
|
||||
|
||||
#if defined(USE_SYSTEMD)
|
||||
if (global.tune.options & GTUNE_USE_SYSTEMD)
|
||||
sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
|
||||
#endif
|
||||
|
||||
signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
|
||||
signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
|
||||
signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
|
||||
signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
|
||||
signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
|
||||
signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
|
||||
|
||||
mworker_unblock_signals();
|
||||
mworker_cleanlisteners();
|
||||
|
||||
global.nbthread = 1;
|
||||
relative_pid = 1;
|
||||
pid_bit = 1;
|
||||
|
||||
jobs++; /* this is the "master" job, we want to take care of the
|
||||
signals even if there is no listener so the poll loop don't
|
||||
leave */
|
||||
|
||||
fork_poller();
|
||||
run_thread_poll_loop((int []){0});
|
||||
}
|
||||
|
||||
/*
|
||||
* Reexec the process in failure mode, instead of exiting
|
||||
@ -1501,7 +1528,7 @@ static void init(int argc, char **argv)
|
||||
if ((global.mode & MODE_MWORKER) && (getenv("HAPROXY_MWORKER_WAIT_ONLY") != NULL)) {
|
||||
|
||||
unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
|
||||
mworker_wait();
|
||||
mworker_loop();
|
||||
}
|
||||
|
||||
if ((global.mode & MODE_MWORKER) && (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
|
||||
@ -2822,8 +2849,6 @@ int main(int argc, char **argv)
|
||||
|
||||
if (proc == global.nbproc) {
|
||||
if (global.mode & MODE_MWORKER) {
|
||||
mworker_cleanlisteners();
|
||||
deinit_pollers();
|
||||
|
||||
if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
|
||||
(global.mode & MODE_DAEMON)) {
|
||||
@ -2835,7 +2860,7 @@ int main(int argc, char **argv)
|
||||
global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
|
||||
}
|
||||
|
||||
mworker_wait();
|
||||
mworker_loop();
|
||||
/* should never get there */
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user