diff --git a/Makefile b/Makefile index 200a5f60d..2a2a21ff9 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). @@ -700,6 +701,12 @@ BUILD_OPTIONS += $(call ignore_implicit,USE_WURFL) OPTIONS_LDFLAGS += $(if $(WURFL_LIB),-L$(WURFL_LIB)) -lwurfl endif +ifneq ($(USE_SYSTEMD),) +BUILD_OPTIONS += $(call ignore_implicit,USE_SYSTEMD) +OPTIONS_CFLAGS += -DUSE_SYSTEMD +OPTIONS_LDFLAGS += -lsystemd +endif + ifneq ($(USE_PCRE)$(USE_STATIC_PCRE)$(USE_PCRE_JIT),) ifneq ($(USE_PCRE2)$(USE_STATIC_PCRE2)$(USE_PCRE2_JIT),) $(error cannot compile both PCRE and PCRE2 support) diff --git a/contrib/systemd/haproxy.service.in b/contrib/systemd/haproxy.service.in index 81b4951df..edbd4c292 100644 --- a/contrib/systemd/haproxy.service.in +++ b/contrib/systemd/haproxy.service.in @@ -7,12 +7,12 @@ After=network.target # socket if you want seamless reloads. Environment="CONFIG=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" ExecStartPre=@SBINDIR@/haproxy -f $CONFIG -c -q -ExecStart=@SBINDIR@/haproxy -W -f $CONFIG -p $PIDFILE +ExecStart=@SBINDIR@/haproxy -Ws -f $CONFIG -p $PIDFILE ExecReload=@SBINDIR@/haproxy -f $CONFIG -c -q ExecReload=/bin/kill -USR2 $MAINPID KillMode=mixed Restart=always -Type=forking +Type=notify [Install] WantedBy=multi-user.target diff --git a/include/types/global.h b/include/types/global.h index 6793c83cd..242b6234a 100644 --- a/include/types/global.h +++ b/include/types/global.h @@ -66,6 +66,7 @@ #define GTUNE_SOCKET_TRANSFER (1<<8) #define GTUNE_EXIT_ONFAILURE (1<<9) +#define GTUNE_USE_SYSTEMD (1<<10) /* Access level for a stats socket */ #define ACCESS_LVL_NONE 0 diff --git a/src/haproxy.c b/src/haproxy.c index ba5a4b208..b39a95fe3 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -61,6 +61,9 @@ #ifdef DEBUG_FULL #include #endif +#if defined(USE_SYSTEMD) +#include +#endif #include #include @@ -404,6 +407,9 @@ static void usage(char *name) " -V enters verbose mode (disables quiet mode)\n" " -D goes daemon ; -C changes to before loading files.\n" " -W master-worker mode.\n" +#if defined(USE_SYSTEMD) + " -Ws master-worker mode with systemd notify support.\n" +#endif " -q quiet mode : don't display messages\n" " -c check mode : only check config files and exit\n" " -n sets the maximum total # of connections (%d)\n" @@ -635,6 +641,10 @@ static void mworker_reload() mworker_block_signals(); mworker_unregister_signals(); +#if defined(USE_SYSTEMD) + if (global.tune.options & GTUNE_USE_SYSTEMD) + sd_notify(0, "RELOADING=1"); +#endif setenv("HAPROXY_MWORKER_REEXEC", "1", 1); /* compute length */ @@ -698,6 +708,11 @@ static void mworker_wait() restart_wait: +#if defined(USE_SYSTEMD) + if (global.tune.options & GTUNE_USE_SYSTEMD) + sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid()); +#endif + mworker_register_signals(); mworker_unblock_signals(); @@ -710,6 +725,11 @@ static void mworker_wait() /* should reach there only if it fail */ goto restart_wait; } else { +#if defined(USE_SYSTEMD) + if ((global.tune.options & GTUNE_USE_SYSTEMD) && (sig == SIGUSR1 || sig == SIGTERM)) { + sd_notify(0, "STOPPING=1"); + } +#endif Warning("Exiting Master process...\n"); mworker_kill(sig); mworker_unregister_signals(); @@ -1342,6 +1362,15 @@ static void init(int argc, char **argv) arg_mode |= MODE_CHECK; else if (*flag == 'D') arg_mode |= MODE_DAEMON; + else if (*flag == 'W' && flag[1] == 's') { + arg_mode |= MODE_MWORKER; +#if defined(USE_SYSTEMD) + global.tune.options |= GTUNE_USE_SYSTEMD; +#else + Alert("master-worker mode with systemd support (-Ws) requested, but not compiled. Use master-worker mode (-W) if you are not using Type=notify in your unit file or recompile with USE_SYSTEMD=1.\n\n"); + usage(progname); +#endif + } else if (*flag == 'W') arg_mode |= MODE_MWORKER; else if (*flag == 'q')