diff --git a/0001-MEDIUM-add-systemd-service.patch b/0001-MEDIUM-add-systemd-service.patch new file mode 100644 index 0000000..94d6f92 --- /dev/null +++ b/0001-MEDIUM-add-systemd-service.patch @@ -0,0 +1,56 @@ +From 4a190f7d08857fec82fa0c07e29e8754d0ba9794 Mon Sep 17 00:00:00 2001 +From: Marc-Antoine Perennou +Date: Fri, 22 Nov 2013 08:28:03 +0100 +Subject: [PATCH 1/5] MEDIUM: add systemd service + +--- + .gitignore | 1 + + contrib/systemd/Makefile | 8 ++++++++ + contrib/systemd/haproxy.service.in | 11 +++++++++++ + 3 files changed, 20 insertions(+) + create mode 100644 contrib/systemd/Makefile + create mode 100644 contrib/systemd/haproxy.service.in + +diff --git a/.gitignore b/.gitignore +index 5d9576af102e..83d84083ca3e 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -15,3 +15,4 @@ haproxy-* + make-* + dlmalloc.c + 00*.patch ++*.service +diff --git a/contrib/systemd/Makefile b/contrib/systemd/Makefile +new file mode 100644 +index 000000000000..e542c2387c79 +--- /dev/null ++++ b/contrib/systemd/Makefile +@@ -0,0 +1,8 @@ ++PREFIX = /usr/local ++SBINDIR = $(PREFIX)/sbin ++ ++haproxy.service: haproxy.service.in ++ sed -e 's:@SBINDIR@:'$(strip $(SBINDIR))':' $< > $@ ++ ++clean: ++ rm -f haproxy.service +diff --git a/contrib/systemd/haproxy.service.in b/contrib/systemd/haproxy.service.in +new file mode 100644 +index 000000000000..1a3d2c050f49 +--- /dev/null ++++ b/contrib/systemd/haproxy.service.in +@@ -0,0 +1,11 @@ ++[Unit] ++Description=HAProxy Load Balancer ++After=network.target ++ ++[Service] ++ExecStart=@SBINDIR@/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid ++ExecReload=/bin/kill -USR2 $MAINPID ++Restart=always ++ ++[Install] ++WantedBy=multi-user.target +-- +1.8.4 + diff --git a/0002-MEDIUM-add-haproxy-systemd-wrapper.patch b/0002-MEDIUM-add-haproxy-systemd-wrapper.patch new file mode 100644 index 0000000..ae92271 --- /dev/null +++ b/0002-MEDIUM-add-haproxy-systemd-wrapper.patch @@ -0,0 +1,227 @@ +From 2e52a44546db246b89817711efec6b046c06d453 Mon Sep 17 00:00:00 2001 +From: Marc-Antoine Perennou +Date: Fri, 22 Nov 2013 08:29:29 +0100 +Subject: [PATCH 2/5] MEDIUM: add haproxy-systemd-wrapper + +Currently, to reload haproxy configuration, you have to use "-sf". + +There is a problem with this way of doing things. First of all, in the systemd world, +reload commands should be "oneshot" ones, which means they should not be the new main +process but rather a tool which makes a call to it and then exits. With the current approach, +the reload command is the new main command and moreover, it makes the previous one exit. +Systemd only tracks the main program, seeing it ending, it assumes it either finished or failed, +and kills everything remaining as a grabage collector. We then end up with no haproxy running +at all. + +This patch adds wrapper around haproxy, no changes at all have been made into it, +so it's not intrusive and doesn't change anything for other hosts. What this wrapper does +is basically launching haproxy as a child, listen to the SIGUSR2 (not to conflict with +haproxy itself) signal, and spawing a new haproxy with "-sf" as a child to relay the +first one. + +Signed-off-by: Marc-Antoine Perennou +--- + .gitignore | 1 + + Makefile | 16 +++++- + src/haproxy-systemd-wrapper.c | 114 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 129 insertions(+), 2 deletions(-) + create mode 100644 src/haproxy-systemd-wrapper.c + +diff --git a/.gitignore b/.gitignore +index 83d84083ca3e..ec1545a7a3df 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 57692fe51ba6..6bb231a0213a 100644 +--- a/Makefile ++++ b/Makefile +@@ -519,7 +519,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/protocols.o \ +@@ -537,12 +537,17 @@ EBTREE_OBJS = $(EBTREE_DIR)/ebtree.o \ + $(EBTREE_DIR)/ebmbtree.o $(EBTREE_DIR)/ebsttree.o \ + $(EBTREE_DIR)/ebimtree.o $(EBTREE_DIR)/ebistree.o + ++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 $@ $^ + +@@ -562,6 +567,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 $@ $< + +@@ -575,9 +585,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 + +@@ -586,6 +597,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 000000000000..596801591b9e +--- /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; ++} +-- +1.8.4 + diff --git a/0003-MEDIUM-New-cli-option-Ds-for-systemd-compatibility.patch b/0003-MEDIUM-New-cli-option-Ds-for-systemd-compatibility.patch new file mode 100644 index 0000000..cb22ecb --- /dev/null +++ b/0003-MEDIUM-New-cli-option-Ds-for-systemd-compatibility.patch @@ -0,0 +1,157 @@ +From 8b79e7c45c86ef57317cbdbf451e49896a8ac239 Mon Sep 17 00:00:00 2001 +From: Marc-Antoine Perennou +Date: Fri, 22 Nov 2013 08:34:52 +0100 +Subject: [PATCH 3/5] MEDIUM: New cli option -Ds for systemd compatibility + +This patch adds a new option "-Ds" which is exactly like "-D", but instead of +forking n times to get n jobs running and then exiting, prefers to wait for all the +children it just created. With this done, haproxy becomes more systemd-compliant, +without changing anything for other systems. + +Signed-off-by: Marc-Antoine Perennou +--- + doc/haproxy.1 | 4 ++++ + include/types/global.h | 1 + + src/haproxy.c | 35 +++++++++++++++++++++++------------ + 3 files changed, 28 insertions(+), 12 deletions(-) + +diff --git a/doc/haproxy.1 b/doc/haproxy.1 +index 001de15a2ff9..48717adefab4 100644 +--- a/doc/haproxy.1 ++++ b/doc/haproxy.1 +@@ -57,6 +57,10 @@ starting up. + Start in daemon mode. + + .TP ++\fB\-Ds\fP ++Start in systemd daemon mode, keeping a process in foreground. ++ ++.TP + \fB\-q\fP + Disable messages on output. + +diff --git a/include/types/global.h b/include/types/global.h +index 7c5346b00b2d..d871939db21d 100644 +--- a/include/types/global.h ++++ b/include/types/global.h +@@ -38,6 +38,7 @@ + #define MODE_VERBOSE 0x10 + #define MODE_STARTING 0x20 + #define MODE_FOREGROUND 0x40 ++#define MODE_SYSTEMD 0x80 + + /* list of last checks to perform, depending on config options */ + #define LSTCHK_CAP_BIND 0x00000001 /* check that we can bind to any port */ +diff --git a/src/haproxy.c b/src/haproxy.c +index 7a09e3fbfd72..494de5c85c29 100644 +--- a/src/haproxy.c ++++ b/src/haproxy.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -488,8 +489,11 @@ void init(int argc, char **argv) + arg_mode |= MODE_DEBUG; + else if (*flag == 'c') + arg_mode |= MODE_CHECK; +- else if (*flag == 'D') ++ else if (*flag == 'D') { + arg_mode |= MODE_DAEMON; ++ if (flag[1] == 's') /* -Ds */ ++ arg_mode |= MODE_SYSTEMD; ++ } + else if (*flag == 'q') + arg_mode |= MODE_QUIET; + else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) { +@@ -541,7 +545,7 @@ void init(int argc, char **argv) + } + + global.mode = MODE_STARTING | /* during startup, we want most of the alerts */ +- (arg_mode & (MODE_DAEMON | MODE_FOREGROUND | MODE_VERBOSE ++ (arg_mode & (MODE_DAEMON | MODE_SYSTEMD | MODE_FOREGROUND | MODE_VERBOSE + | MODE_QUIET | MODE_CHECK | MODE_DEBUG)); + + if (LIST_ISEMPTY(&cfg_cfgfiles)) +@@ -649,24 +653,24 @@ void init(int argc, char **argv) + + if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) { + /* command line debug mode inhibits configuration mode */ +- global.mode &= ~(MODE_DAEMON | MODE_QUIET); ++ global.mode &= ~(MODE_DAEMON | MODE_SYSTEMD | MODE_QUIET); + global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)); + } + +- if (arg_mode & MODE_DAEMON) { ++ if (arg_mode & (MODE_DAEMON | MODE_SYSTEMD)) { + /* command line daemon mode inhibits foreground and debug modes mode */ + global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND); +- global.mode |= (arg_mode & MODE_DAEMON); ++ global.mode |= (arg_mode & (MODE_DAEMON | MODE_SYSTEMD)); + } + + global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE)); + +- if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) { +- Warning(" mode incompatible with and . Keeping only.\n"); +- global.mode &= ~(MODE_DAEMON | MODE_QUIET); ++ if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_SYSTEMD | MODE_QUIET))) { ++ Warning(" mode incompatible with , and . Keeping only.\n"); ++ global.mode &= ~(MODE_DAEMON | MODE_SYSTEMD | MODE_QUIET); + } + +- if ((global.nbproc > 1) && !(global.mode & MODE_DAEMON)) { ++ if ((global.nbproc > 1) && !(global.mode & (MODE_DAEMON | MODE_SYSTEMD))) { + if (!(global.mode & (MODE_FOREGROUND | MODE_DEBUG))) + Warning(" is only meaningful in daemon mode. Setting limit to 1 process.\n"); + global.nbproc = 1; +@@ -1132,7 +1136,7 @@ int main(int argc, char **argv) + } + + /* open log & pid files before the chroot */ +- if (global.mode & MODE_DAEMON && global.pidfile != NULL) { ++ if (global.mode & (MODE_DAEMON | MODE_SYSTEMD) && global.pidfile != NULL) { + int pidfd; + unlink(global.pidfile); + pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644); +@@ -1222,9 +1226,10 @@ int main(int argc, char **argv) + argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock, global.maxsock); + } + +- if (global.mode & MODE_DAEMON) { ++ if (global.mode & (MODE_DAEMON | MODE_SYSTEMD)) { + struct proxy *px; + int ret = 0; ++ int *children = calloc(global.nbproc, sizeof(int)); + int proc; + + /* the father launches the required number of processes */ +@@ -1237,6 +1242,7 @@ int main(int argc, char **argv) + } + else if (ret == 0) /* child breaks here */ + break; ++ children[proc] = ret; + if (pidfile != NULL) { + fprintf(pidfile, "%d\n", ret); + fflush(pidfile); +@@ -1262,8 +1268,13 @@ int main(int argc, char **argv) + px = px->next; + } + +- if (proc == global.nbproc) ++ if (proc == global.nbproc) { ++ if (global.mode & MODE_SYSTEMD) { ++ for (proc = 0; proc < global.nbproc; proc++) ++ while (waitpid(children[proc], NULL, 0) == -1 && errno == EINTR); ++ } + exit(0); /* parent must leave */ ++ } + + /* if we're NOT in QUIET mode, we should now close the 3 first FDs to ensure + * that we can detach from the TTY. We MUST NOT do it in other cases since +-- +1.8.4 + diff --git a/0004-BUG-MEDIUM-systemd-wrapper-don-t-leak-zombie-process.patch b/0004-BUG-MEDIUM-systemd-wrapper-don-t-leak-zombie-process.patch new file mode 100644 index 0000000..28fe071 --- /dev/null +++ b/0004-BUG-MEDIUM-systemd-wrapper-don-t-leak-zombie-process.patch @@ -0,0 +1,64 @@ +From f0b6dab91180d0f719ff486b4bdf4ba518436174 Mon Sep 17 00:00:00 2001 +From: Marc-Antoine Perennou +Date: Fri, 22 Nov 2013 08:36:01 +0100 +Subject: [PATCH 4/5] BUG/MEDIUM: systemd-wrapper: don't leak zombie processes + +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 waiting randomly every child we spawn. + +Signed-off-by: Marc-Antoine Perennou +--- + src/haproxy-systemd-wrapper.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c +index 596801591b9e..8499b35188c5 100644 +--- a/src/haproxy-systemd-wrapper.c ++++ b/src/haproxy-systemd-wrapper.c +@@ -19,12 +19,11 @@ + #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) ++static void spawn_haproxy(char **pid_strv, int nb_pid) + { + pid_t pid = fork(); + if (!pid) { +@@ -45,7 +44,6 @@ static pid_t spawn_haproxy(char **pid_strv, int nb_pid) + execv(argv[0], argv); + exit(0); + } +- return pid; + } + + static int read_pids(char ***pid_strv) +@@ -77,7 +75,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); ++ spawn_haproxy(pid_strv, nb_pid); + + for (i = 0; i < nb_pid; ++i) + free(pid_strv[i]); +@@ -107,8 +105,8 @@ int main(int argc, char **argv) + + signal(SIGUSR2, &signal_handler); + +- pid = spawn_haproxy(NULL, 0); +- while (-1 != waitpid(pid, NULL, 0) || errno == EINTR); ++ spawn_haproxy(NULL, 0); ++ while (-1 != wait(NULL) || errno == EINTR); + + return EXIT_SUCCESS; + } +-- +1.8.4 + diff --git a/0005-BUILD-stdbool-is-not-portable-again.patch b/0005-BUILD-stdbool-is-not-portable-again.patch new file mode 100644 index 0000000..5aca70f --- /dev/null +++ b/0005-BUILD-stdbool-is-not-portable-again.patch @@ -0,0 +1,25 @@ +From 18d4a296b1a3bcdf6de904582d4766c1345a1b2f Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Fri, 22 Nov 2013 08:37:33 +0100 +Subject: [PATCH 5/5] BUILD: stdbool is not portable (again) + +Another build issue on Solaris without c99. Please don't use stdbool. +--- + src/haproxy-systemd-wrapper.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c +index 8499b35188c5..fb1a7fd92724 100644 +--- a/src/haproxy-systemd-wrapper.c ++++ b/src/haproxy-systemd-wrapper.c +@@ -12,7 +12,6 @@ + + #include + #include +-#include + #include + #include + #include +-- +1.8.4 + diff --git a/haproxy-1.2.16_config_haproxy_user.patch b/0006-haproxy-1.2.16_config_haproxy_user.patch similarity index 100% rename from haproxy-1.2.16_config_haproxy_user.patch rename to 0006-haproxy-1.2.16_config_haproxy_user.patch diff --git a/haproxy-makefile_lib.patch b/0007-haproxy-makefile_lib.patch similarity index 100% rename from haproxy-makefile_lib.patch rename to 0007-haproxy-makefile_lib.patch diff --git a/0008-MEDIUM-haproxy-systemd-wrapper-Revised-implementatio.patch b/0008-MEDIUM-haproxy-systemd-wrapper-Revised-implementatio.patch new file mode 100644 index 0000000..c76efed --- /dev/null +++ b/0008-MEDIUM-haproxy-systemd-wrapper-Revised-implementatio.patch @@ -0,0 +1,124 @@ +From bf1c645a89c2c6df3c35cf489b3dba53e91e69c5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Kristoffer=20Gr=C3=B6nlund?= +Date: Fri, 22 Nov 2013 10:47:27 +0100 +Subject: [PATCH] MEDIUM: haproxy-systemd-wrapper: Revised implementation + +* Locate haproxy using location of the wrapper +* Kill children when killed +* Write information to stdout +--- + src/haproxy-systemd-wrapper.c | 57 +++++++++++++++++++++++++++++++++++++------ + 1 file changed, 50 insertions(+), 7 deletions(-) + +diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c +index fb1a7fd92724..4ca86dd3b8c0 100644 +--- a/src/haproxy-systemd-wrapper.c ++++ b/src/haproxy-systemd-wrapper.c +@@ -22,15 +22,30 @@ static char *pid_file = "/run/haproxy.pid"; + static int main_argc; + static char **main_argv; + ++static void locate_haproxy(char *buffer, size_t buffer_size) ++{ ++ char* end; ++ readlink("/proc/self/exe", buffer, buffer_size); ++ end = strrchr(buffer, '/'); ++ if (end == NULL) ++ strncpy(buffer, "/usr/sbin/haproxy", buffer_size); ++ end[1] = '\0'; ++ strncat(buffer, "haproxy", buffer_size); ++} ++ + static void spawn_haproxy(char **pid_strv, int nb_pid) + { +- pid_t pid = fork(); ++ char haproxy_bin[512]; ++ pid_t pid; ++ ++ 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"; ++ locate_haproxy(haproxy_bin, 512); ++ argv[argno++] = haproxy_bin; + for (i = 0; i < main_argc; ++i) + argv[argno++] = main_argv[i]; + argv[argno++] = "-Ds"; +@@ -40,6 +55,12 @@ static void spawn_haproxy(char **pid_strv, int nb_pid) + argv[argno++] = pid_strv[i]; + } + argv[argno] = NULL; ++ ++ printf("%s", "haproxy-systemd-wrapper: executing "); ++ for (i = 0; argv[i]; ++i) ++ printf("%s ", argv[i]); ++ puts(""); ++ + execv(argv[0], argv); + exit(0); + } +@@ -68,7 +89,7 @@ static int read_pids(char ***pid_strv) + return read; + } + +-static void signal_handler(int signum __attribute__((unused))) ++static void sigusr2_handler(int signum __attribute__((unused))) + { + int i; + char **pid_strv = NULL; +@@ -81,6 +102,22 @@ static void signal_handler(int signum __attribute__((unused))) + free(pid_strv); + } + ++static void sigint_handler(int signum __attribute__((unused))) ++{ ++ int i, pid; ++ char **pid_strv = NULL; ++ int nb_pid = read_pids(&pid_strv); ++ for (i = 0; i < nb_pid; ++i) { ++ pid = atoi(pid_strv[i]); ++ if (pid > 0) { ++ printf("haproxy-systemd-wrapper: SIGINT -> %d\n", pid); ++ kill(pid, SIGINT); ++ free(pid_strv[i]); ++ } ++ } ++ free(pid_strv); ++} ++ + static void init(int argc, char **argv) + { + while (argc > 1) { +@@ -96,16 +133,22 @@ static void init(int argc, char **argv) + + int main(int argc, char **argv) + { ++ int status; ++ + --argc; ++argv; +- main_argc = argc; +- main_argv = argv; ++ main_argc = argc; ++ main_argv = argv; + + init(argc, argv); + +- signal(SIGUSR2, &signal_handler); ++ signal(SIGINT, &sigint_handler); ++ signal(SIGUSR2, &sigusr2_handler); + + spawn_haproxy(NULL, 0); +- while (-1 != wait(NULL) || errno == EINTR); ++ status = -1; ++ while (-1 != wait(&status) || errno == EINTR) ++ ; + ++ printf("haproxy-systemd-wrapper: exit, haproxy RC=%d\n", status); + return EXIT_SUCCESS; + } +-- +1.8.4 + diff --git a/haproxy.changes b/haproxy.changes index 4c5a973..8ee93eb 100644 --- a/haproxy.changes +++ b/haproxy.changes @@ -1,3 +1,20 @@ +------------------------------------------------------------------- +Fri Nov 22 09:54:48 UTC 2013 - kgronlund@suse.com + +- Backport haproxy-systemd-wrapper from upstream +- Patch haproxy-systemd-wrapper to work on openSUSE + +------------------------------------------------------------------- +Thu Oct 31 12:46:04 UTC 2013 - kgronlund@suse.com + +- Remove duplicate Requires: from .spec file. + +------------------------------------------------------------------- +Thu Oct 31 12:41:12 UTC 2013 - kgronlund@suse.com + +- Re-enable sysvinit support for older versions + (server:http still builds for older versions) + ------------------------------------------------------------------- Mon Oct 28 14:32:00 UTC 2013 - p.drouand@gmail.com diff --git a/haproxy.init b/haproxy.init new file mode 100644 index 0000000..57fd237 --- /dev/null +++ b/haproxy.init @@ -0,0 +1,248 @@ +#!/bin/sh +# +### BEGIN INIT INFO +# Provides: haproxy +# Required-Start: $syslog $remote_fs +# Should-Start: $time ypbind sendmail +# Required-Stop: $syslog $remote_fs +# Should-Stop: $time ypbind sendmail +# Default-Start: 3 5 +# Default-Stop: 0 1 2 6 +# Short-Description: haproxy +# Description: Start haproxy a reliable, high performance TCP/HTTP load balancer +### END INIT INFO +# +# Any extensions to the keywords given above should be preceeded by +# X-VendorTag- (X-UnitedLinux- X-SuSE- for us) according to LSB. +# +# Notes on Required-Start/Should-Start: +# * There are two different issues that are solved by Required-Start +# and Should-Start +# (a) Hard dependencies: This is used by the runlevel editor to determine +# which services absolutely need to be started to make the start of +# this service make sense. Example: nfsserver should have +# Required-Start: $portmap +# Also, required services are started before the dependent ones. +# The runlevel editor will warn about such missing hard dependencies +# and suggest enabling. During system startup, you may expect an error, +# if the dependency is not fulfilled. +# (b) Specifying the init script ordering, not real (hard) dependencies. +# This is needed by insserv to determine which service should be +# started first (and at a later stage what services can be started +# in parallel). The tag Should-Start: is used for this. +# It tells, that if a service is available, it should be started +# before. If not, never mind. +# * When specifying hard dependencies or ordering requirements, you can +# use names of services (contents of their Provides: section) +# or pseudo names starting with a $. The following ones are available +# according to LSB (1.1): +# $local_fs all local file systems are mounted +# (most services should need this!) +# $remote_fs all remote file systems are mounted +# (note that /usr may be remote, so +# many services should Require this!) +# $syslog system logging facility up +# $network low level networking (eth card, ...) +# $named hostname resolution available +# $netdaemons all network daemons are running +# The $netdaemons pseudo service has been removed in LSB 1.2. +# For now, we still offer it for backward compatibility. +# These are new (LSB 1.2): +# $time the system time has been set correctly +# $portmap SunRPC portmapping service available +# UnitedLinux extensions: +# $ALL indicates that a script should be inserted +# at the end +# * The services specified in the stop tags +# (Required-Stop/Should-Stop) +# specify which services need to be still running when this service +# is shut down. Often the entries there are just copies or a subset +# from the respective start tag. +# * Should-Start/Stop are now part of LSB as of 2.0, +# formerly SUSE/Unitedlinux used X-UnitedLinux-Should-Start/-Stop. +# insserv does support both variants. +# * X-UnitedLinux-Default-Enabled: yes/no is used at installation time +# (%fillup_and_insserv macro in %post of many RPMs) to specify whether +# a startup script should default to be enabled after installation. +# It's not used by insserv. +# +# Note on runlevels: +# 0 - halt/poweroff 6 - reboot +# 1 - single user 2 - multiuser without network exported +# 3 - multiuser w/ network (text mode) 5 - multiuser w/ network and X11 (xdm) +# +# Note on script names: +# http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/scrptnames.html +# A registry has been set up to manage the init script namespace. +# http://www.lanana.org/ +# Please use the names already registered or register one or use a +# vendor prefix. + + +# Check for missing binaries (stale symlinks should not happen) +# Note: Special treatment of stop for LSB conformance +HAPROXY_BIN=/usr/sbin/haproxy +test -x $HAPROXY_BIN || { echo "$HAPROXY_BIN not installed"; + if [ "$1" = "stop" ]; then exit 0; + else exit 5; fi; } +HAPROXY_PID="/var/run/haproxy.pid" +HAPROXY_CONF="/etc/haproxy/haproxy.cfg" +## Check for existence of needed config file and read it +#HAPROXY_CONFIG=/etc/sysconfig/haproxy +#test -r $HAPROXY_CONFIG || { echo "$HAPROXY_CONFIG not existing"; +# if [ "$1" = "stop" ]; then exit 0; +# else exit 6; fi; } +# +## Read config +#. $HAPROXY_CONFIG + +# Source LSB init functions +# providing start_daemon, killproc, pidofproc, +# log_success_msg, log_failure_msg and log_warning_msg. +# This is currently not used by UnitedLinux based distributions and +# not needed for init scripts for UnitedLinux only. If it is used, +# the functions from rc.status should not be sourced or used. +#. /lib/lsb/init-functions + +# Shell functions sourced from /etc/rc.status: +# rc_check check and set local and overall rc status +# rc_status check and set local and overall rc status +# rc_status -v be verbose in local rc status and clear it afterwards +# rc_status -v -r ditto and clear both the local and overall rc status +# rc_status -s display "skipped" and exit with status 3 +# rc_status -u display "unused" and exit with status 3 +# rc_failed set local and overall rc status to failed +# rc_failed set local and overall rc status to +# rc_reset clear both the local and overall rc status +# rc_exit exit appropriate to overall rc status +# rc_active checks whether a service is activated by symlinks +. /etc/rc.status + +# Reset status of this service +rc_reset + +# Return values acc. to LSB for all commands but status: +# 0 - success +# 1 - generic or unspecified error +# 2 - invalid or excess argument(s) +# 3 - unimplemented feature (e.g. "reload") +# 4 - user had insufficient privileges +# 5 - program is not installed +# 6 - program is not configured +# 7 - program is not running +# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) +# +# Note that starting an already running service, stopping +# or restarting a not-running service as well as the restart +# with force-reload (in case signaling is not supported) are +# considered a success. + +function haproxy_check() { + HAPROXY_CONFIG_CHECK="$($HAPROXY_BIN -c -q -f $HAPROXY_CONF 2>&1)" + if [ $? -ne 0 ] ; then + echo "" >&2 + echo "$HAPROXY_CONFIG_CHECK" >&2 + rc_failed + rc_status -v + exit 1 + else + return 0 + fi +} + +case "$1" in + start) + echo -n "Starting haproxy " + ## Start daemon with startproc(8). If this fails + ## the return value is set appropriately by startproc. + haproxy_check + /sbin/startproc $HAPROXY_BIN -D -f $HAPROXY_CONF -p $HAPROXY_PID + # Remember status and be verbose + rc_status -v + ;; + stop) + echo -n "Shutting down haproxy " + ## Stop daemon with killproc(8) and if this fails + ## killproc sets the return value according to LSB. + + /sbin/killproc -TERM $HAPROXY_BIN + + # Remember status and be verbose + rc_status -v + ;; + try-restart|condrestart) + ## Do a restart only if the service was active before. + ## Note: try-restart is now part of LSB (as of 1.9). + ## RH has a similar command named condrestart. + if test "$1" = "condrestart"; then + echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}" + fi + $0 status + if test $? = 0; then + # we us reload here for a graceful restart during update + $0 reload + else + rc_reset # Not running is not a failure. + fi + # Remember status and be quiet + rc_status + ;; + restart) + ## Stop the service and regardless of whether it was + ## running or not, start it again. + haproxy_check + $0 stop + $0 start + + # Remember status and be quiet + rc_status + ;; + check) + ## Stop the service and regardless of whether it was + ## running or not, start it again. + echo -n "Checking config of haproxy " + haproxy_check + rc_status -v + ;; + reload|force-reload) + ## Like force-reload, but if daemon does not support + ## signaling, do nothing (!) + + haproxy_check + # If it supports signaling: + echo -n "Reload service haproxy " + $HAPROXY_BIN -p $HAPROXY_PID -D -f $HAPROXY_CONF -sf $(cat $HAPROXY_PID) + rc_status -v + ;; + status) + echo -n "Checking for service haproxy " + ## Check status with checkproc(8), if process is running + ## checkproc will return with exit status 0. + + # Return value is slightly different for the status command: + # 0 - service up and running + # 1 - service dead, but /var/run/ pid file exists + # 2 - service dead, but /var/lock/ lock file exists + # 3 - service not running (unused) + # 4 - service status unknown :-( + # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) + + # NOTE: checkproc returns LSB compliant status values. + /sbin/checkproc $HAPROXY_BIN + # NOTE: rc_status knows that we called this init script with + # "status" option and adapts its messages accordingly. + rc_status -v + ;; + probe) + ## Optional: Probe for the necessity of a reload, print out the + ## argument to this init script which is required for a reload. + ## Note: probe is not (yet) part of LSB (as of 1.9) + + test $HAPROXY_CONF -nt $HAPROXY_PID && echo reload + ;; + *) + echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}" + exit 1 + ;; +esac +rc_exit diff --git a/haproxy.service b/haproxy.service deleted file mode 100644 index 3b7773f..0000000 --- a/haproxy.service +++ /dev/null @@ -1,13 +0,0 @@ -[Unit] -Description=HAProxy For TCP And HTTP Based Applications -After=network.target - -[Service] -Type=forking -PIDFile=/run/haproxy.pid -ExecStartPre=/usr/sbin/haproxy -c -q -f /etc/haproxy/haproxy.cfg -ExecStart=/usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -ExecReload=/bin/bash -c "exec /usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -sf $MAINPID" - -[Install] -WantedBy=multi-user.target diff --git a/haproxy.spec b/haproxy.spec index 4b8726c..b4210db 100644 --- a/haproxy.spec +++ b/haproxy.spec @@ -13,33 +13,47 @@ # published by the Open Source Initiative. # Please submit bugfixes or comments via http://bugs.opensuse.org/ +# + Name: haproxy Version: 1.4.24 Release: 0 # -License: GPL-2.0+ and LGPL-2.1+ -Group: Productivity/Networking/Web/Proxy # -BuildRequires: libgcrypt-devel -BuildRequires: pcre-devel libgcrypt-devel -BuildRequires: udev +%if 0%{?suse_version} >= 1230 BuildRequires: pkgconfig(systemd) +%endif +BuildRoot: %{_tmppath}/%{name}-%{version}-build +BuildRequires: libgcrypt-devel +BuildRequires: pcre-devel +BuildRequires: udev %define pkg_name haproxy %define pkg_home /var/lib/%{pkg_name} # Url: http://haproxy.1wt.eu/ Source: http://haproxy.1wt.eu/download/1.4/src/haproxy-%{version}.tar.gz -Source1: %{pkg_name}.service +Source1: %{pkg_name}.init Source2: http://haproxy.1wt.eu/download/contrib/haproxy.vim -Patch1: haproxy-1.2.16_config_haproxy_user.patch -Patch2: haproxy-makefile_lib.patch +Patch1: 0001-MEDIUM-add-systemd-service.patch +Patch2: 0002-MEDIUM-add-haproxy-systemd-wrapper.patch +Patch3: 0003-MEDIUM-New-cli-option-Ds-for-systemd-compatibility.patch +Patch4: 0004-BUG-MEDIUM-systemd-wrapper-don-t-leak-zombie-process.patch +Patch5: 0005-BUILD-stdbool-is-not-portable-again.patch +Patch6: 0006-haproxy-1.2.16_config_haproxy_user.patch +Patch7: 0007-haproxy-makefile_lib.patch +Patch8: 0008-MEDIUM-haproxy-systemd-wrapper-Revised-implementatio.patch Source99: haproxy-rpmlintrc # Summary: The Reliable, High Performance TCP/HTTP Load Balancer +License: GPL-2.0+ and LGPL-2.1+ +Group: Productivity/Networking/Web/Proxy Provides: %{name}-doc = %{version} Obsoletes: %{name}-doc < %{version} + +%if 0%{?suse_version} >= 1230 %{?systemd_requires} +%endif %description HAProxy implements an event-driven, mono-process model which enables support @@ -54,8 +68,14 @@ the most work done from every CPU cycle. %prep %setup -q -%patch1 -%patch2 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p0 +%patch7 -p0 +%patch8 -p1 %build %{__make} \ @@ -66,20 +86,37 @@ the most work done from every CPU cycle. LIB="%{_lib}" \ DEBUG="%{optflags} -fno-strict-aliasing" +%{__make} PREFIX="%{_prefix}" -C contrib/systemd + %install %{__install} -D -m 0755 %{pkg_name} %{buildroot}%{_sbindir}/%{pkg_name} %{__install} -D -m 0644 examples/%{pkg_name}.cfg %{buildroot}%{_sysconfdir}/%{pkg_name}/%{pkg_name}.cfg -%{__install} -D -m 0755 %{S:1} %{buildroot}%{_unitdir}/%{pkg_name}.service + +%if 0%{?suse_version} >= 1230 +%{__install} -D -m 0755 haproxy-systemd-wrapper %{buildroot}%{_sbindir}/haproxy-systemd-wrapper +%{__install} -D -m 0755 contrib/systemd/%{pkg_name}.service %{buildroot}%{_unitdir}/%{pkg_name}.service ln -sf /sbin/service %{buildroot}%{_sbindir}/rc%{pkg_name} +%else +%{__install} -D -m 0755 %{S:1} %{buildroot}%{_sysconfdir}/init.d/%{pkg_name} +%{__ln_s} -f %{_sysconfdir}/init.d/%{pkg_name} %{buildroot}%{_sbindir}/rc%{pkg_name} +%endif + %{__install} -d -m 0755 %{buildroot}%{pkg_home} %{__install} -D -m 0644 %{S:2} %{buildroot}%{_datadir}/%{pkg_name}/%{pkg_name}.vim %{__install} -D -m 0644 doc/%{pkg_name}.1 %{buildroot}%{_mandir}/man1/%{pkg_name}.1 gzip %{buildroot}%{_mandir}/man1/%{pkg_name}.1 +%if 0%{?suse_version} < 1230 +%clean +%{?buildroot:%{__rm} -rf %{buildroot}} +%endif + %pre /usr/sbin/groupadd -r %{pkg_name} &>/dev/null ||: /usr/sbin/useradd -g %{pkg_name} -s /bin/false -r -c "user for %{pkg_name}" -d %{pkg_home} %{pkg_name} &>/dev/null ||: +%if 0%{?suse_version} >= 1230 + %post %service_add_post %{pkg_name}.service @@ -89,13 +126,38 @@ gzip %{buildroot}%{_mandir}/man1/%{pkg_name}.1 %postun %service_del_postun %{pkg_name}.service +%else + +%post +%fillup_and_insserv %{pkg_name} + +%preun +%stop_on_removal %{pkg_name} + +%postun +%restart_on_update %{pkg_name} +%{insserv_cleanup} + +%endif + %files %defattr(-,root,root,-) %doc CHANGELOG README LICENSE %doc ROADMAP TODO doc/* examples %dir %{_sysconfdir}/%{pkg_name} %config(noreplace) %{_sysconfdir}/%{pkg_name}/%{pkg_name}.cfg + +%if 0%{?suse_version} >= 1230 + %{_unitdir}/%{pkg_name}.service +%{_sbindir}/haproxy-systemd-wrapper + +%else + +%config(noreplace) %{_sysconfdir}/init.d/%{pkg_name} + +%endif + %{_sbindir}/haproxy %{_sbindir}/rchaproxy %{pkg_home}