Formerly, if A was replaced by B, and then B by C before A finished exiting, we didn't wait for B to finish so it ended up as a zombie process. Fix this by queuing all process we spawn for waitpid.
Signed-off-by: Marc-Antoine Perennou <marc-anto...@perennou.com> --- src/haproxy-systemd-wrapper.c | 45 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c index 5968015..a3af528 100644 --- a/src/haproxy-systemd-wrapper.c +++ b/src/haproxy-systemd-wrapper.c @@ -24,6 +24,44 @@ static char *pid_file = "/run/haproxy.pid"; static int main_argc; static char **main_argv; +static struct { + pid_t *queue; + int count; + int size; + int index; + int rindex; +} pids = { + .queue = NULL, + .count = 0, + .size = 8, + .index = 0, + .rindex = 0 +}; + +static void pids_push(pid_t pid) +{ + if (pids.size == pids.count) { + // Double the capacity, write in the new half, rewind reading head + pids.index = pids.size; + pids.rindex = 0; + pids.size *= 2; + pids.queue = realloc(pids.queue, pids.size * sizeof(int)); + } + pids.queue[pids.index++ % pids.size] = pid; + pids.count++; +} + +static bool pids_pop(void) +{ + if (pids.count == 0) + pid = 0; + else { + pids.count--; + pid = pids.queue[pids.rindex++ % pids.size]; + } + return pid != 0; +} + static pid_t spawn_haproxy(char **pid_strv, int nb_pid) { pid_t pid = fork(); @@ -77,7 +115,7 @@ static void signal_handler(int signum __attribute__((unused))) char **pid_strv = NULL; int nb_pid = read_pids(&pid_strv); - pid = spawn_haproxy(pid_strv, nb_pid); + pids_push(spawn_haproxy(pid_strv, nb_pid)); for (i = 0; i < nb_pid; ++i) free(pid_strv[i]); @@ -107,8 +145,11 @@ int main(int argc, char **argv) signal(SIGUSR2, &signal_handler); + pids.queue = malloc(pids.size * sizeof(int)); pid = spawn_haproxy(NULL, 0); - while (-1 != waitpid(pid, NULL, 0) || errno == EINTR); + while ((-1 != waitpid(pid, NULL, 0) && pids_pop()) || errno == EINTR); + + free(pids.queue); return EXIT_SUCCESS; } -- 1.8.1.5