Signed-off-by: Marc-Antoine Perennou <marc-anto...@perennou.com> --- .gitignore | 1 + Makefile | 16 +++++- src/haproxy-systemd-wrapper.c | 122 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 src/haproxy-systemd-wrapper.c
diff --git a/.gitignore b/.gitignore index 5d9576a..5e6f556 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ src/*.o *.log* *.trace* haproxy-* +!src/*.c make-* dlmalloc.c 00*.patch diff --git a/Makefile b/Makefile index f1eed55..ca9e1b2 100644 --- a/Makefile +++ b/Makefile @@ -593,7 +593,7 @@ all: @echo @exit 1 else -all: haproxy +all: haproxy haproxy-systemd-wrapper endif OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocol.o \ @@ -618,12 +618,17 @@ ifneq ($(TRACE),) OBJS += src/trace.o endif +WRAPPER_OBJS = src/haproxy-systemd-wrapper.o + # Not used right now LIB_EBTREE = $(EBTREE_DIR)/libebtree.a haproxy: $(OBJS) $(OPTIONS_OBJS) $(EBTREE_OBJS) $(LD) $(LDFLAGS) -o $@ $^ $(LDOPTS) +haproxy-systemd-wrapper: $(WRAPPER_OBJS) + $(LD) $(LDFLAGS) -o $@ $^ $(LDOPTS) + $(LIB_EBTREE): $(EBTREE_OBJS) $(AR) rv $@ $^ @@ -646,6 +651,11 @@ src/haproxy.o: src/haproxy.c -DBUILD_OPTIONS='"$(strip $(BUILD_OPTIONS))"' \ -c -o $@ $< +src/haproxy-systemd-wrapper.o: src/haproxy-systemd-wrapper.c + $(CC) $(COPTS) \ + -DSBINDIR='"$(strip $(SBINDIR))"' \ + -c -o $@ $< + src/dlmalloc.o: $(DLMALLOC_SRC) $(CC) $(COPTS) -DDEFAULT_MMAP_THRESHOLD=$(DLMALLOC_THRES) -c -o $@ $< @@ -659,9 +669,10 @@ install-doc: install -m 644 doc/$$x.txt $(DESTDIR)$(DOCDIR) ; \ done -install-bin: haproxy +install-bin: haproxy haproxy-systemd-wrapper install -d $(DESTDIR)$(SBINDIR) install haproxy $(DESTDIR)$(SBINDIR) + install haproxy-systemd-wrapper $(DESTDIR)$(SBINDIR) install: install-bin install-man install-doc @@ -670,6 +681,7 @@ clean: for dir in . src include/* doc ebtree; do rm -f $$dir/*~ $$dir/*.rej $$dir/core; done rm -f haproxy-$(VERSION).tar.gz haproxy-$(VERSION)$(SUBVERS).tar.gz rm -f haproxy-$(VERSION) nohup.out gmon.out + rm -f haproxy-systemd-wrapper tags: find src include \( -name '*.c' -o -name '*.h' \) -print0 | \ diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c new file mode 100644 index 0000000..aa509f6 --- /dev/null +++ b/src/haproxy-systemd-wrapper.c @@ -0,0 +1,122 @@ +/* + * Wrapper to make haproxy systemd-compliant. + * + * Copyright 2013 Marc-Antoine Perennou <marc-anto...@perennou.com> + * + * 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. + * + */ + +#include <limits.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> + +#define MAX_ARGS 10 + +static pid_t pid = 0; +static const char *conf_file = "/etc/haproxy/haproxy.cfg"; +static const char *pid_file = "/run/haproxy.pid"; + +static pid_t exec_bg(char **pid_strv, int nb_pid, char *arg, ...) +{ + pid_t pid = fork(); + if (!pid) { + char **argv = calloc(MAX_ARGS + nb_pid + 1, sizeof(char *)); + int i; + int argno = 0; + va_list al; + va_start(al, arg); + while (arg && argno < MAX_ARGS + 1) { + argv[argno++] = arg; + arg = va_arg(al, char *); + } + va_end (al); + for (i = 0; i < nb_pid; ++i) + argv[argno++] = pid_strv[i]; + argv[argno] = NULL; + execv(argv[0], argv); + exit(0); + } else return pid; +} + +static int read_pids(char ***pid_strv) +{ + FILE *f = fopen(pid_file, "r"); + int read = 0, allocated = 8; + char pid_str[10]; + + if (!f) + return 0; + + *pid_strv = malloc(allocated * sizeof(char *)); + while (1 == fscanf(f, "%s\n", pid_str)) { + if (read == allocated) { + allocated *= 2; + *pid_strv = realloc(*pid_strv, allocated * sizeof(char *)); + } + (*pid_strv)[read++] = strdup(pid_str); + } + + fclose(f); + + return read; +} + +static void signal_handler(int signum __attribute__((unused))) +{ + int i; + char **pid_strv = NULL; + int nb_pid = read_pids(&pid_strv); + + pid = exec_bg(pid_strv, nb_pid, SBINDIR"/haproxy", "-Ds", "-f", conf_file, "-p", pid_file, "-sf", NULL); + + for (i = 0; i < nb_pid; ++i) + free(pid_strv[i]); + free(pid_strv); +} + +static void usage(const char *progname) +{ + fprintf(stderr, "Usage: %s [-f cfgfile] [-p pidfile]\n", progname); + exit(1); +} + +static void init(int argc, char **argv) +{ + const char *progname = *argv; + --argc; ++argv; + while (argc > 0) { + const char *flag; + if (**argv != '-' || argc == 1) + usage(progname); + flag = *argv + 1; + --argc; ++argv; + switch (*flag) { + case 'f': conf_file = *argv; break; + case 'p': pid_file = *argv; break; + default: usage(progname); + } + --argc; ++argv; + } +} + +int main(int argc, char **argv) +{ + init(argc, argv); + + signal(SIGUSR2, &signal_handler); + + pid = exec_bg(NULL, 0, SBINDIR"/haproxy", "-Ds", "-f", conf_file, "-p", pid_file, NULL); + while (-1 != waitpid(pid, NULL, 0)); + + return EXIT_SUCCESS; +} -- 1.8.1.2