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 <Marc-Antoine@Perennou.com>
This commit is contained in:
Marc-Antoine Perennou 2013-02-12 10:53:52 +01:00 committed by Willy Tarreau
parent fce2e96b9d
commit 992709bad0
5 changed files with 30 additions and 12 deletions

View File

@ -51,6 +51,7 @@ There are only a few command line options :
= 'maxconn' in 'listen' or 'default' sections = 'maxconn' in 'listen' or 'default' sections
-d starts in foregreound with debugging mode enabled -d starts in foregreound with debugging mode enabled
-D starts in daemon mode -D starts in daemon mode
-Ds starts in systemd daemon mode
-q disable messages on output -q disable messages on output
-V displays messages on output even when -q or 'quiet' are specified. -V displays messages on output even when -q or 'quiet' are specified.
-c only checks config file and exits with code 0 if no error was found, or -c only checks config file and exits with code 0 if no error was found, or

View File

@ -53,6 +53,7 @@ Les options de lancement sont peu nombreuses :
= 'maxconn' dans les sections 'listen' ou 'default' = 'maxconn' dans les sections 'listen' ou 'default'
-d active le mode debug -d active le mode debug
-D passe en daemon -D passe en daemon
-Ds passe en daemon systemd
-q désactive l'affichage de messages sur la sortie standard. -q désactive l'affichage de messages sur la sortie standard.
-V affiche les messages sur la sortie standard, même si -q ou 'quiet' sont -V affiche les messages sur la sortie standard, même si -q ou 'quiet' sont
spécifiés. spécifiés.

View File

@ -56,6 +56,10 @@ starting up.
\fB\-D\fP \fB\-D\fP
Start in daemon mode. Start in daemon mode.
.TP
\fB\-Ds\fP
Start in systemd daemon mode, keeping a process in foreground.
.TP .TP
\fB\-q\fP \fB\-q\fP
Disable messages on output. Disable messages on output.

View File

@ -42,6 +42,7 @@
#define MODE_VERBOSE 0x10 #define MODE_VERBOSE 0x10
#define MODE_STARTING 0x20 #define MODE_STARTING 0x20
#define MODE_FOREGROUND 0x40 #define MODE_FOREGROUND 0x40
#define MODE_SYSTEMD 0x80
/* list of last checks to perform, depending on config options */ /* list of last checks to perform, depending on config options */
#define LSTCHK_CAP_BIND 0x00000001 /* check that we can bind to any port */ #define LSTCHK_CAP_BIND 0x00000001 /* check that we can bind to any port */

View File

@ -42,6 +42,7 @@
#include <signal.h> #include <signal.h>
#include <stdarg.h> #include <stdarg.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/wait.h>
#include <time.h> #include <time.h>
#include <syslog.h> #include <syslog.h>
#include <grp.h> #include <grp.h>
@ -539,8 +540,11 @@ void init(int argc, char **argv)
arg_mode |= MODE_DEBUG; arg_mode |= MODE_DEBUG;
else if (*flag == 'c') else if (*flag == 'c')
arg_mode |= MODE_CHECK; arg_mode |= MODE_CHECK;
else if (*flag == 'D') else if (*flag == 'D') {
arg_mode |= MODE_DAEMON; arg_mode |= MODE_DAEMON;
if (flag[1] == 's') /* -Ds */
arg_mode |= MODE_SYSTEMD;
}
else if (*flag == 'q') else if (*flag == 'q')
arg_mode |= MODE_QUIET; arg_mode |= MODE_QUIET;
else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) { else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
@ -594,7 +598,7 @@ void init(int argc, char **argv)
} }
global.mode = MODE_STARTING | /* during startup, we want most of the alerts */ 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)); | MODE_QUIET | MODE_CHECK | MODE_DEBUG));
if (LIST_ISEMPTY(&cfg_cfgfiles)) if (LIST_ISEMPTY(&cfg_cfgfiles))
@ -733,24 +737,24 @@ void init(int argc, char **argv)
if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) { if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
/* command line debug mode inhibits configuration mode */ /* 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)); 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 */ /* command line daemon mode inhibits foreground and debug modes mode */
global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND); 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)); global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) { if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_SYSTEMD | MODE_QUIET))) {
Warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n"); Warning("<debug> mode incompatible with <quiet>, <daemon> and <systemd>. Keeping <debug> only.\n");
global.mode &= ~(MODE_DAEMON | MODE_QUIET); 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))) if (!(global.mode & (MODE_FOREGROUND | MODE_DEBUG)))
Warning("<nbproc> is only meaningful in daemon mode. Setting limit to 1 process.\n"); Warning("<nbproc> is only meaningful in daemon mode. Setting limit to 1 process.\n");
global.nbproc = 1; global.nbproc = 1;
@ -1355,7 +1359,7 @@ int main(int argc, char **argv)
} }
/* open log & pid files before the chroot */ /* 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) {
unlink(global.pidfile); unlink(global.pidfile);
pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644); pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (pidfd < 0) { if (pidfd < 0) {
@ -1443,9 +1447,10 @@ int main(int argc, char **argv)
argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock, global.maxsock); 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; struct proxy *px;
int ret = 0; int ret = 0;
int *children = calloc(global.nbproc, sizeof(int));
int proc; int proc;
/* the father launches the required number of processes */ /* the father launches the required number of processes */
@ -1458,6 +1463,7 @@ int main(int argc, char **argv)
} }
else if (ret == 0) /* child breaks here */ else if (ret == 0) /* child breaks here */
break; break;
children[proc] = ret;
if (pidfd >= 0) { if (pidfd >= 0) {
char pidstr[100]; char pidstr[100];
snprintf(pidstr, sizeof(pidstr), "%d\n", ret); snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
@ -1493,8 +1499,13 @@ int main(int argc, char **argv)
px = px->next; 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 */ exit(0); /* parent must leave */
}
/* if we're NOT in QUIET mode, we should now close the 3 first FDs to ensure /* 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 * that we can detach from the TTY. We MUST NOT do it in other cases since