diff --git a/.gitignore b/.gitignore index 5d9576af1..5e6f556c0 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 f1eed55e5..ca9e1b2db 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 000000000..596801591 --- /dev/null +++ b/src/haproxy-systemd-wrapper.c @@ -0,0 +1,114 @@ +/* + * Wrapper to make haproxy systemd-compliant. + * + * Copyright 2013 Marc-Antoine Perennou + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +static pid_t pid = 0; +static char *pid_file = "/run/haproxy.pid"; +static int main_argc; +static char **main_argv; + +static pid_t spawn_haproxy(char **pid_strv, int nb_pid) +{ + pid_t pid = fork(); + if (!pid) { + /* 3 for "haproxy -Ds -sf" */ + char **argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *)); + int i; + int argno = 0; + argv[argno++] = SBINDIR"/haproxy"; + for (i = 0; i < main_argc; ++i) + argv[argno++] = main_argv[i]; + argv[argno++] = "-Ds"; + if (nb_pid > 0) { + argv[argno++] = "-sf"; + for (i = 0; i < nb_pid; ++i) + argv[argno++] = pid_strv[i]; + } + argv[argno] = NULL; + execv(argv[0], argv); + exit(0); + } + 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 = spawn_haproxy(pid_strv, nb_pid); + + for (i = 0; i < nb_pid; ++i) + free(pid_strv[i]); + free(pid_strv); +} + +static void init(int argc, char **argv) +{ + while (argc > 1) { + if (**argv == '-') { + char *flag = *argv + 1; + --argc; ++argv; + if (*flag == 'p') + pid_file = *argv; + } + --argc; ++argv; + } +} + +int main(int argc, char **argv) +{ + --argc; ++argv; + main_argc = argc; + main_argv = argv; + + init(argc, argv); + + signal(SIGUSR2, &signal_handler); + + pid = spawn_haproxy(NULL, 0); + while (-1 != waitpid(pid, NULL, 0) || errno == EINTR); + + return EXIT_SUCCESS; +}