Hello,

I have packaged haproxy 1.4.24 for openSUSE 13.1 [1], which uses systemd
as the init system. At first I tried using a service script originally
written for Fedora, but this script didn't handle configuration file
reload in a good way. I then found the haproxy-systemd-wrapper
committed upstream, which looked like a more viable approach. However,
it didn't work for openSUSE mainly because SBINDIR didn't point to the
correct directory.

There was also an issue with the wrapper not cleaning up when killed by
systemd, leaving zombie processes hanging.

The attached patches should address both of these issues in a way that
should work on any systemd-platform. I also added some logging to the
systemd-wrapper so that it's easier to figure out what it does.

The patched wrapper seems to work well for me, but any
comments/suggestions are welcome. :)

In case the patches get stripped, they are also available from my
github account [2]. They are applied to a copy of 1.4.24 there, but
should apply cleanly to the development tree.

[1]:
https://build.opensuse.org/package/show/network:ha-clustering:Factory/haproxy

[2]: https://github.com/krig/haproxy-1.4/commits/master

-- 
// Kristoffer Grönlund
// [email protected]
>From 6c5c12ecbfe9bf084a2271c367afd2e436cfc118 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kristoffer=20Gr=C3=B6nlund?= <[email protected]>
Date: Fri, 22 Nov 2013 11:06:34 +0100
Subject: [PATCH 1/3] MEDIUM: haproxy-systemd-wrapper: Use haproxy in same
 directory

Locate the wrapper and use a haproxy executable found in the
same directory.

This patch lets the wrapper work in openSUSE.
---
 src/haproxy-systemd-wrapper.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c
index fb1a7fd92724..6546616b79ee 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";
-- 
1.8.4

>From 89d7f82dfa92e01fdb265d4c453fa939b1d9d672 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kristoffer=20Gr=C3=B6nlund?= <[email protected]>
Date: Fri, 22 Nov 2013 11:09:39 +0100
Subject: [PATCH 2/3] MEDIUM: systemd-wrapper: Kill child processes when
 interrupted

Send SIGINT to child processes when killed. This ensures that
the haproxy process managed by the systemd-wrapper is stopped
when "systemctl stop haproxy.service" is called.
---
 src/haproxy-systemd-wrapper.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c
index 6546616b79ee..d337f4c0d44e 100644
--- a/src/haproxy-systemd-wrapper.c
+++ b/src/haproxy-systemd-wrapper.c
@@ -83,7 +83,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;
@@ -96,6 +96,21 @@ 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) {
+			kill(pid, SIGINT);
+			free(pid_strv[i]);
+		}
+	}
+	free(pid_strv);
+}
+
 static void init(int argc, char **argv)
 {
 	while (argc > 1) {
@@ -117,7 +132,8 @@ int main(int argc, char **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);
-- 
1.8.4

>From 39939ea72cc7402c2bdff14099c52363f0bf830f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kristoffer=20Gr=C3=B6nlund?= <[email protected]>
Date: Fri, 22 Nov 2013 11:11:54 +0100
Subject: [PATCH 3/3] LOW: systemd-wrapper: Write debug information to stdout

Write the command line used to call haproxy to stdout, as
well as the return code returned by the haproxy process.
---
 src/haproxy-systemd-wrapper.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c
index d337f4c0d44e..4ca86dd3b8c0 100644
--- a/src/haproxy-systemd-wrapper.c
+++ b/src/haproxy-systemd-wrapper.c
@@ -55,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);
 	}
@@ -104,6 +110,7 @@ static void sigint_handler(int signum __attribute__((unused)))
 	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]);
 		}
@@ -126,9 +133,11 @@ 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);
 
@@ -136,7 +145,10 @@ int main(int argc, char **argv)
 	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

Reply via email to