Tim Düsterhus
2017-11-18 19:02:23 UTC
This patch adds support for `Type=notify` to the systemd unit.
Supporting `Type=notify` improves both starting as well as reloading
of the unit, because systemd will be let known when the action completed.
the reload actually succeeded.
This patch introduces a new `USE_SYSTEMD` option which controls including
the sd-daemon library.
When `USE_SYSTEMD` is enabled and haproxy is running in mworker mode it will
send status messages to systemd using `sd_notify()` in the following cases:
- The master process forked off the worker processes (READY=1)
- The master process entered the `mworker_reload()` function (RELOADING=1)
- The master process received the SIGUSR1 or SIGTERM signal (STOPPING=1)
Status messages are not sent when not using the mworker mode, because using
mworker is recommended when using systemd.
Change the unit file to specify `Type=notify` as well as `KillSignal=USR1` to
support cleaner shutdowns. Systemd will kill haproxy using SIGKILL if
connections remain after 90 seconds (by default). Remove KillSignal=USR1 if
the SIGKILL is undesired.
Future evolutions of this feature could include making use of the `STATUS`
feature of `sd_notify()` to send information about the number of active
connections to systemd. This would require bidirectional communication
between the master and the workers and thus is left for future work.
---
Makefile | 6 ++++++
contrib/systemd/haproxy.service.in | 3 ++-
src/haproxy.c | 16 ++++++++++++++++
3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 200a5f60d..e1eab0c2e 100644
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,7 @@
# USE_DEVICEATLAS : enable DeviceAtlas api.
# USE_51DEGREES : enable third party device detection library from 51Degrees
# USE_WURFL : enable WURFL detection library from Scientiamobile
+# USE_SYSTEMD : enable sd_notify() support.
#
# Options can be forced by specifying "USE_xxx=1" or can be disabled by using
# "USE_xxx=" (empty string).
@@ -608,6 +609,11 @@ endif
OPTIONS_OBJS += src/ssl_sock.o
endif
+ifneq ($(USE_SYSTEMD),)
+OPTIONS_CFLAGS += -DUSE_SYSTEMD
+OPTIONS_LDFLAGS += -lsystemd
+endif
+
# The private cache option affect the way the shctx is built
ifneq ($(USE_PRIVATE_CACHE),)
OPTIONS_CFLAGS += -DUSE_PRIVATE_CACHE
diff --git a/contrib/systemd/haproxy.service.in b/contrib/systemd/haproxy.service.in
index 81b4951df..895e3b036 100644
--- a/contrib/systemd/haproxy.service.in
+++ b/contrib/systemd/haproxy.service.in
@@ -11,8 +11,9 @@ ExecStart=@SBINDIR@/haproxy -W -f $CONFIG -p $PIDFILE
ExecReload=@SBINDIR@/haproxy -f $CONFIG -c -q
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
+KillSignal=USR1
Restart=always
-Type=forking
+Type=notify
[Install]
WantedBy=multi-user.target
diff --git a/src/haproxy.c b/src/haproxy.c
index ba5a4b208..63c29023d 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -61,6 +61,9 @@
#ifdef DEBUG_FULL
#include <assert.h>
#endif
+#ifdef USE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
#include <common/base64.h>
#include <common/cfgparse.h>
@@ -635,6 +638,9 @@ static void mworker_reload()
mworker_block_signals();
mworker_unregister_signals();
+#if USE_SYSTEMD
+ sd_notify(0, "RELOADING=1");
+#endif
setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
/* compute length */
@@ -682,6 +688,7 @@ static void mworker_reload()
return;
alloc_error:
+
Warning("Failed to reexecute the master processs [%d]: Cannot allocate memory\n", pid);
return;
}
@@ -698,6 +705,10 @@ static void mworker_wait()
restart_wait:
+#if USE_SYSTEMD
+ sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
+#endif
+
mworker_register_signals();
mworker_unblock_signals();
@@ -710,6 +721,11 @@ restart_wait:
/* should reach there only if it fail */
goto restart_wait;
} else {
+#if USE_SYSTEMD
+ if (sig == SIGUSR1 || sig == SIGTERM) {
+ sd_notify(0, "STOPPING=1");
+ }
+#endif
Warning("Exiting Master process...\n");
mworker_kill(sig);
mworker_unregister_signals();
Supporting `Type=notify` improves both starting as well as reloading
of the unit, because systemd will be let known when the action completed.
Note however that reloading a daemon by sending a signal (as with the
example line above) is usually not a good choice, because this is an
asynchronous operation and hence not suitable to order reloads of
multiple services against each other. It is strongly recommended to
set ExecReload= to a command that not only triggers a configuration
reload of the daemon, but also synchronously waits for it to complete.
By making systemd aware of a reload in progress it is able to wait untilexample line above) is usually not a good choice, because this is an
asynchronous operation and hence not suitable to order reloads of
multiple services against each other. It is strongly recommended to
set ExecReload= to a command that not only triggers a configuration
reload of the daemon, but also synchronously waits for it to complete.
the reload actually succeeded.
This patch introduces a new `USE_SYSTEMD` option which controls including
the sd-daemon library.
When `USE_SYSTEMD` is enabled and haproxy is running in mworker mode it will
send status messages to systemd using `sd_notify()` in the following cases:
- The master process forked off the worker processes (READY=1)
- The master process entered the `mworker_reload()` function (RELOADING=1)
- The master process received the SIGUSR1 or SIGTERM signal (STOPPING=1)
Status messages are not sent when not using the mworker mode, because using
mworker is recommended when using systemd.
Change the unit file to specify `Type=notify` as well as `KillSignal=USR1` to
support cleaner shutdowns. Systemd will kill haproxy using SIGKILL if
connections remain after 90 seconds (by default). Remove KillSignal=USR1 if
the SIGKILL is undesired.
Future evolutions of this feature could include making use of the `STATUS`
feature of `sd_notify()` to send information about the number of active
connections to systemd. This would require bidirectional communication
between the master and the workers and thus is left for future work.
---
Makefile | 6 ++++++
contrib/systemd/haproxy.service.in | 3 ++-
src/haproxy.c | 16 ++++++++++++++++
3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 200a5f60d..e1eab0c2e 100644
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,7 @@
# USE_DEVICEATLAS : enable DeviceAtlas api.
# USE_51DEGREES : enable third party device detection library from 51Degrees
# USE_WURFL : enable WURFL detection library from Scientiamobile
+# USE_SYSTEMD : enable sd_notify() support.
#
# Options can be forced by specifying "USE_xxx=1" or can be disabled by using
# "USE_xxx=" (empty string).
@@ -608,6 +609,11 @@ endif
OPTIONS_OBJS += src/ssl_sock.o
endif
+ifneq ($(USE_SYSTEMD),)
+OPTIONS_CFLAGS += -DUSE_SYSTEMD
+OPTIONS_LDFLAGS += -lsystemd
+endif
+
# The private cache option affect the way the shctx is built
ifneq ($(USE_PRIVATE_CACHE),)
OPTIONS_CFLAGS += -DUSE_PRIVATE_CACHE
diff --git a/contrib/systemd/haproxy.service.in b/contrib/systemd/haproxy.service.in
index 81b4951df..895e3b036 100644
--- a/contrib/systemd/haproxy.service.in
+++ b/contrib/systemd/haproxy.service.in
@@ -11,8 +11,9 @@ ExecStart=@SBINDIR@/haproxy -W -f $CONFIG -p $PIDFILE
ExecReload=@SBINDIR@/haproxy -f $CONFIG -c -q
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
+KillSignal=USR1
Restart=always
-Type=forking
+Type=notify
[Install]
WantedBy=multi-user.target
diff --git a/src/haproxy.c b/src/haproxy.c
index ba5a4b208..63c29023d 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -61,6 +61,9 @@
#ifdef DEBUG_FULL
#include <assert.h>
#endif
+#ifdef USE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
#include <common/base64.h>
#include <common/cfgparse.h>
@@ -635,6 +638,9 @@ static void mworker_reload()
mworker_block_signals();
mworker_unregister_signals();
+#if USE_SYSTEMD
+ sd_notify(0, "RELOADING=1");
+#endif
setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
/* compute length */
@@ -682,6 +688,7 @@ static void mworker_reload()
return;
alloc_error:
+
Warning("Failed to reexecute the master processs [%d]: Cannot allocate memory\n", pid);
return;
}
@@ -698,6 +705,10 @@ static void mworker_wait()
restart_wait:
+#if USE_SYSTEMD
+ sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
+#endif
+
mworker_register_signals();
mworker_unblock_signals();
@@ -710,6 +721,11 @@ restart_wait:
/* should reach there only if it fail */
goto restart_wait;
} else {
+#if USE_SYSTEMD
+ if (sig == SIGUSR1 || sig == SIGTERM) {
+ sd_notify(0, "STOPPING=1");
+ }
+#endif
Warning("Exiting Master process...\n");
mworker_kill(sig);
mworker_unregister_signals();
--
2.15.0
2.15.0