~ubuntu-branches/debian/stretch/haproxy/stretch

« back to all changes in this revision

Viewing changes to src/haproxy-systemd-wrapper.c

  • Committer: Package Import Robot
  • Author(s): Apollon Oikonomopoulos
  • Date: 2014-06-20 11:05:17 UTC
  • mfrom: (1.1.15) (15.1.12 experimental)
  • Revision ID: package-import@ubuntu.com-20140620110517-u6q5p9kyy2f3ozw9
Tags: 1.5.0-1
* New upstream stable series. Notable changes since the 1.4 series:
  + Native SSL support on both sides with SNI/NPN/ALPN and OCSP stapling.
  + IPv6 and UNIX sockets are supported everywhere
  + End-to-end HTTP keep-alive for better support of NTLM and improved
    efficiency in static farms
  + HTTP/1.1 response compression (deflate, gzip) to save bandwidth
  + PROXY protocol versions 1 and 2 on both sides
  + Data sampling on everything in request or response, including payload
  + ACLs can use any matching method with any input sample
  + Maps and dynamic ACLs updatable from the CLI
  + Stick-tables support counters to track activity on any input sample
  + Custom format for logs, unique-id, header rewriting, and redirects
  + Improved health checks (SSL, scripted TCP, check agent, ...)
  + Much more scalable configuration supports hundreds of thousands of
    backends and certificates without sweating

* Upload to unstable, merge all 1.5 work from experimental. Most important
  packaging changes since 1.4.25-1 include:
  + systemd support.
  + A more sane default config file.
  + Zero-downtime upgrades between 1.5 releases by gracefully reloading
    HAProxy during upgrades.
  + HTML documentation shipped in the haproxy-doc package.
  + kqueue support for kfreebsd.

* Packaging changes since 1.5~dev26-2:
  + Drop patches merged upstream:
    o Fix-reference-location-in-manpage.patch
    o 0001-BUILD-stats-workaround-stupid-and-bogus-Werror-forma.patch
  + d/watch: look for stable 1.5 releases
  + systemd: respect CONFIG and EXTRAOPTS when specified in
    /etc/default/haproxy.
  + initscript: test the configuration before start or reload.
  + initscript: remove the ENABLED flag and logic.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Wrapper to make haproxy systemd-compliant.
 
3
 *
 
4
 * Copyright 2013 Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
 
5
 *
 
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.
 
10
 *
 
11
 */
 
12
 
 
13
#include <errno.h>
 
14
#include <signal.h>
 
15
#include <stdio.h>
 
16
#include <stdlib.h>
 
17
#include <string.h>
 
18
#include <unistd.h>
 
19
#include <sys/wait.h>
 
20
 
 
21
#define REEXEC_FLAG "HAPROXY_SYSTEMD_REEXEC"
 
22
#define SD_DEBUG "<7>"
 
23
#define SD_NOTICE "<5>"
 
24
 
 
25
static char *pid_file = "/run/haproxy.pid";
 
26
static int wrapper_argc;
 
27
static char **wrapper_argv;
 
28
 
 
29
static void locate_haproxy(char *buffer, size_t buffer_size)
 
30
{
 
31
        char *end = NULL;
 
32
 
 
33
        if (readlink("/proc/self/exe", buffer, buffer_size) > 0)
 
34
                end = strrchr(buffer, '/');
 
35
 
 
36
        if (end == NULL) {
 
37
                strncpy(buffer, "/usr/sbin/haproxy", buffer_size);
 
38
                return;
 
39
        }
 
40
        end[1] = '\0';
 
41
        strncpy(end + 1, "haproxy", buffer + buffer_size - (end + 1));
 
42
        buffer[buffer_size - 1] = '\0';
 
43
}
 
44
 
 
45
static void spawn_haproxy(char **pid_strv, int nb_pid)
 
46
{
 
47
        char haproxy_bin[512];
 
48
        pid_t pid;
 
49
        int main_argc;
 
50
        char **main_argv;
 
51
 
 
52
        main_argc = wrapper_argc - 1;
 
53
        main_argv = wrapper_argv + 1;
 
54
 
 
55
        pid = fork();
 
56
        if (!pid) {
 
57
                /* 3 for "haproxy -Ds -sf" */
 
58
                char **argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *));
 
59
                int i;
 
60
                int argno = 0;
 
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";
 
66
                if (nb_pid > 0) {
 
67
                        argv[argno++] = "-sf";
 
68
                        for (i = 0; i < nb_pid; ++i)
 
69
                                argv[argno++] = pid_strv[i];
 
70
                }
 
71
                argv[argno] = NULL;
 
72
 
 
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");
 
77
 
 
78
                execv(argv[0], argv);
 
79
                exit(0);
 
80
        }
 
81
}
 
82
 
 
83
static int read_pids(char ***pid_strv)
 
84
{
 
85
        FILE *f = fopen(pid_file, "r");
 
86
        int read = 0, allocated = 8;
 
87
        char pid_str[10];
 
88
 
 
89
        if (!f)
 
90
                return 0;
 
91
 
 
92
        *pid_strv = malloc(allocated * sizeof(char *));
 
93
        while (1 == fscanf(f, "%s\n", pid_str)) {
 
94
                if (read == allocated) {
 
95
                        allocated *= 2;
 
96
                        *pid_strv = realloc(*pid_strv, allocated * sizeof(char *));
 
97
                }
 
98
                (*pid_strv)[read++] = strdup(pid_str);
 
99
        }
 
100
 
 
101
        fclose(f);
 
102
 
 
103
        return read;
 
104
}
 
105
 
 
106
static void sigusr2_handler(int signum __attribute__((unused)))
 
107
{
 
108
        setenv(REEXEC_FLAG, "1", 1);
 
109
        fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: re-executing\n");
 
110
 
 
111
        execv(wrapper_argv[0], wrapper_argv);
 
112
}
 
113
 
 
114
static void sigint_handler(int signum __attribute__((unused)))
 
115
{
 
116
        int i, pid;
 
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]);
 
121
                if (pid > 0) {
 
122
                        fprintf(stderr, SD_DEBUG "haproxy-systemd-wrapper: SIGINT -> %d\n", pid);
 
123
                        kill(pid, SIGINT);
 
124
                        free(pid_strv[i]);
 
125
                }
 
126
        }
 
127
        free(pid_strv);
 
128
}
 
129
 
 
130
static void init(int argc, char **argv)
 
131
{
 
132
        while (argc > 1) {
 
133
                if (**argv == '-') {
 
134
                        char *flag = *argv + 1;
 
135
                        --argc; ++argv;
 
136
                        if (*flag == 'p')
 
137
                                pid_file = *argv;
 
138
                }
 
139
                --argc; ++argv;
 
140
        }
 
141
}
 
142
 
 
143
int main(int argc, char **argv)
 
144
{
 
145
        int status;
 
146
 
 
147
        wrapper_argc = argc;
 
148
        wrapper_argv = argv;
 
149
 
 
150
        --argc; ++argv;
 
151
        init(argc, argv);
 
152
 
 
153
        signal(SIGINT, &sigint_handler);
 
154
        signal(SIGUSR2, &sigusr2_handler);
 
155
 
 
156
        if (getenv(REEXEC_FLAG) != NULL) {
 
157
                /* We are being re-executed: restart HAProxy gracefully */
 
158
                int i;
 
159
                char **pid_strv = NULL;
 
160
                int nb_pid = read_pids(&pid_strv);
 
161
                sigset_t sigs;
 
162
 
 
163
                unsetenv(REEXEC_FLAG);
 
164
                spawn_haproxy(pid_strv, nb_pid);
 
165
 
 
166
                /* Unblock SIGUSR2 which was blocked by the signal handler
 
167
                 * before re-exec */
 
168
                sigprocmask(SIG_BLOCK, NULL, &sigs);
 
169
                sigdelset(&sigs, SIGUSR2);
 
170
                sigprocmask(SIG_SETMASK, &sigs, NULL);
 
171
 
 
172
                for (i = 0; i < nb_pid; ++i)
 
173
                        free(pid_strv[i]);
 
174
                free(pid_strv);
 
175
        }
 
176
        else {
 
177
                /* Start a fresh copy of HAProxy */
 
178
                spawn_haproxy(NULL, 0);
 
179
        }
 
180
 
 
181
        status = -1;
 
182
        while (-1 != wait(&status) || errno == EINTR)
 
183
                ;
 
184
 
 
185
        fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: exit, haproxy RC=%d\n",
 
186
                        status);
 
187
        return status;
 
188
}