2
* Wrapper to make haproxy systemd-compliant.
4
* Copyright 2013 Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version
9
* 2 of the License, or (at your option) any later version.
21
#define REEXEC_FLAG "HAPROXY_SYSTEMD_REEXEC"
22
#define SD_DEBUG "<7>"
23
#define SD_NOTICE "<5>"
25
static char *pid_file = "/run/haproxy.pid";
26
static int wrapper_argc;
27
static char **wrapper_argv;
29
static void locate_haproxy(char *buffer, size_t buffer_size)
33
if (readlink("/proc/self/exe", buffer, buffer_size) > 0)
34
end = strrchr(buffer, '/');
37
strncpy(buffer, "/usr/sbin/haproxy", buffer_size);
41
strncpy(end + 1, "haproxy", buffer + buffer_size - (end + 1));
42
buffer[buffer_size - 1] = '\0';
45
static void spawn_haproxy(char **pid_strv, int nb_pid)
47
char haproxy_bin[512];
52
main_argc = wrapper_argc - 1;
53
main_argv = wrapper_argv + 1;
57
/* 3 for "haproxy -Ds -sf" */
58
char **argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *));
61
locate_haproxy(haproxy_bin, 512);
62
argv[argno++] = haproxy_bin;
63
for (i = 0; i < main_argc; ++i)
64
argv[argno++] = main_argv[i];
65
argv[argno++] = "-Ds";
67
argv[argno++] = "-sf";
68
for (i = 0; i < nb_pid; ++i)
69
argv[argno++] = pid_strv[i];
73
fprintf(stderr, SD_DEBUG "haproxy-systemd-wrapper: executing ");
74
for (i = 0; argv[i]; ++i)
75
fprintf(stderr, "%s ", argv[i]);
76
fprintf(stderr, "\n");
83
static int read_pids(char ***pid_strv)
85
FILE *f = fopen(pid_file, "r");
86
int read = 0, allocated = 8;
92
*pid_strv = malloc(allocated * sizeof(char *));
93
while (1 == fscanf(f, "%s\n", pid_str)) {
94
if (read == allocated) {
96
*pid_strv = realloc(*pid_strv, allocated * sizeof(char *));
98
(*pid_strv)[read++] = strdup(pid_str);
106
static void sigusr2_handler(int signum __attribute__((unused)))
108
setenv(REEXEC_FLAG, "1", 1);
109
fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: re-executing\n");
111
execv(wrapper_argv[0], wrapper_argv);
114
static void sigint_handler(int signum __attribute__((unused)))
117
char **pid_strv = NULL;
118
int nb_pid = read_pids(&pid_strv);
119
for (i = 0; i < nb_pid; ++i) {
120
pid = atoi(pid_strv[i]);
122
fprintf(stderr, SD_DEBUG "haproxy-systemd-wrapper: SIGINT -> %d\n", pid);
130
static void init(int argc, char **argv)
134
char *flag = *argv + 1;
143
int main(int argc, char **argv)
153
signal(SIGINT, &sigint_handler);
154
signal(SIGUSR2, &sigusr2_handler);
156
if (getenv(REEXEC_FLAG) != NULL) {
157
/* We are being re-executed: restart HAProxy gracefully */
159
char **pid_strv = NULL;
160
int nb_pid = read_pids(&pid_strv);
163
unsetenv(REEXEC_FLAG);
164
spawn_haproxy(pid_strv, nb_pid);
166
/* Unblock SIGUSR2 which was blocked by the signal handler
168
sigprocmask(SIG_BLOCK, NULL, &sigs);
169
sigdelset(&sigs, SIGUSR2);
170
sigprocmask(SIG_SETMASK, &sigs, NULL);
172
for (i = 0; i < nb_pid; ++i)
177
/* Start a fresh copy of HAProxy */
178
spawn_haproxy(NULL, 0);
182
while (-1 != wait(&status) || errno == EINTR)
185
fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: exit, haproxy RC=%d\n",