Signed-off-by: heil <heil@terminal-consulting.de>lilik-openwrt-22.03
@ -1,131 +0,0 @@ | |||||
From a72d39058a7a5d004e0c6b69a91663591bb3bf89 Mon Sep 17 00:00:00 2001 | |||||
From: Vincent Bernat <vincent@bernat.im> | |||||
Date: Thu, 19 May 2016 11:15:51 +0200 | |||||
Subject: [PATCH 1/4] BUG/MAJOR: fix listening IP address storage for frontends | |||||
When compiled with GCC 6, the IP address specified for a frontend was | |||||
ignored and HAProxy was listening on all addresses instead. This is | |||||
caused by an incomplete copy of a "struct sockaddr_storage". | |||||
With the GNU Libc, "struct sockaddr_storage" is defined as this: | |||||
struct sockaddr_storage | |||||
{ | |||||
sa_family_t ss_family; | |||||
unsigned long int __ss_align; | |||||
char __ss_padding[(128 - (2 * sizeof (unsigned long int)))]; | |||||
}; | |||||
Doing an aggregate copy (ss1 = ss2) is different than using memcpy(): | |||||
only members of the aggregate have to be copied. Notably, padding can be | |||||
or not be copied. In GCC 6, some optimizations use this fact and if a | |||||
"struct sockaddr_storage" contains a "struct sockaddr_in", the port and | |||||
the address are part of the padding (between sa_family and __ss_align) | |||||
and can be not copied over. | |||||
Therefore, we replace any aggregate copy by a memcpy(). There is another | |||||
place using the same pattern. We also fix a function receiving a "struct | |||||
sockaddr_storage" by copy instead of by reference. Since it only needs a | |||||
read-only copy, the function is converted to request a reference. | |||||
This is a backport for 1.5 of 6e6158 and 6e46ff1. | |||||
--- | |||||
src/cfgparse.c | 4 ++-- | |||||
src/connection.c | 2 +- | |||||
src/proto_http.c | 12 ++++++------ | |||||
src/proto_tcp.c | 2 +- | |||||
4 files changed, 10 insertions(+), 10 deletions(-) | |||||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||||
index 39abf6b..9331415 100644 | |||||
--- a/src/cfgparse.c | |||||
+++ b/src/cfgparse.c | |||||
@@ -280,7 +280,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, | |||||
} | |||||
/* OK the address looks correct */ | |||||
- ss = *ss2; | |||||
+ memcpy(&ss, ss2, sizeof(ss)); | |||||
for (; port <= end; port++) { | |||||
l = (struct listener *)calloc(1, sizeof(struct listener)); | |||||
@@ -291,7 +291,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, | |||||
l->bind_conf = bind_conf; | |||||
l->fd = fd; | |||||
- l->addr = ss; | |||||
+ memcpy(&l->addr, &ss, sizeof(ss)); | |||||
l->xprt = &raw_sock; | |||||
l->state = LI_INIT; | |||||
diff --git a/src/connection.c b/src/connection.c | |||||
index dab1c90..09fd04e 100644 | |||||
--- a/src/connection.c | |||||
+++ b/src/connection.c | |||||
@@ -620,7 +620,7 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec | |||||
const char pp2_signature[] = PP2_SIGNATURE; | |||||
int ret = 0; | |||||
struct proxy_hdr_v2 *hdr = (struct proxy_hdr_v2 *)buf; | |||||
- struct sockaddr_storage null_addr = {0}; | |||||
+ struct sockaddr_storage null_addr = { .ss_family = 0 }; | |||||
struct sockaddr_storage *src = &null_addr; | |||||
struct sockaddr_storage *dst = &null_addr; | |||||
#ifdef USE_OPENSSL | |||||
diff --git a/src/proto_http.c b/src/proto_http.c | |||||
index b3aa4d8..0b13c5e 100644 | |||||
--- a/src/proto_http.c | |||||
+++ b/src/proto_http.c | |||||
@@ -3220,15 +3220,15 @@ int http_handle_stats(struct session *s, struct channel *req) | |||||
/* Sets the TOS header in IPv4 and the traffic class header in IPv6 packets | |||||
* (as per RFC3260 #4 and BCP37 #4.2 and #5.2). | |||||
*/ | |||||
-static inline void inet_set_tos(int fd, struct sockaddr_storage from, int tos) | |||||
+static inline void inet_set_tos(int fd, struct sockaddr_storage *from, int tos) | |||||
{ | |||||
#ifdef IP_TOS | |||||
- if (from.ss_family == AF_INET) | |||||
+ if (from->ss_family == AF_INET) | |||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); | |||||
#endif | |||||
#ifdef IPV6_TCLASS | |||||
- if (from.ss_family == AF_INET6) { | |||||
- if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&from)->sin6_addr)) | |||||
+ if (from->ss_family == AF_INET6) { | |||||
+ if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)from)->sin6_addr)) | |||||
/* v4-mapped addresses need IP_TOS */ | |||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); | |||||
else | |||||
@@ -3366,7 +3366,7 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct session | |||||
case HTTP_REQ_ACT_SET_TOS: | |||||
if ((cli_conn = objt_conn(s->req->prod->end)) && conn_ctrl_ready(cli_conn)) | |||||
- inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos); | |||||
+ inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, rule->arg.tos); | |||||
break; | |||||
case HTTP_REQ_ACT_SET_MARK: | |||||
@@ -3563,7 +3563,7 @@ http_res_get_intercept_rule(struct proxy *px, struct list *rules, struct session | |||||
case HTTP_RES_ACT_SET_TOS: | |||||
if ((cli_conn = objt_conn(s->req->prod->end)) && conn_ctrl_ready(cli_conn)) | |||||
- inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos); | |||||
+ inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, rule->arg.tos); | |||||
break; | |||||
case HTTP_RES_ACT_SET_MARK: | |||||
diff --git a/src/proto_tcp.c b/src/proto_tcp.c | |||||
index cfa62f7..8c06441 100644 | |||||
--- a/src/proto_tcp.c | |||||
+++ b/src/proto_tcp.c | |||||
@@ -394,7 +394,7 @@ int tcp_connect_server(struct connection *conn, int data, int delack) | |||||
struct sockaddr_storage sa; | |||||
ret = 1; | |||||
- sa = src->source_addr; | |||||
+ memcpy(&sa, &src->source_addr, sizeof(sa)); | |||||
do { | |||||
/* note: in case of retry, we may have to release a previously | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,53 @@ | |||||
From 42ccea00f69abdd1bb748494f7e17d8369ccae31 Mon Sep 17 00:00:00 2001 | |||||
From: Dinko Korunic <dinko.korunic@gmail.com> | |||||
Date: Fri, 9 Sep 2016 09:41:15 +0200 | |||||
Subject: [PATCH 01/26] BUG/MINOR: Fix OSX compilation errors | |||||
SOL_IPV6 is not defined on OSX, breaking the compile. Also libcrypt is | |||||
not available for installation neither in Macports nor as a Brew recipe, | |||||
so we're disabling implicit dependancy. | |||||
Signed-off-by: Dinko Korunic <dinko.korunic@gmail.com> | |||||
(cherry picked from commit 7276f3aa3d687fca64bb9becc66c8e0dbb8b378a) | |||||
--- | |||||
Makefile | 1 - | |||||
src/proto_tcp.c | 4 ++-- | |||||
2 files changed, 2 insertions(+), 3 deletions(-) | |||||
diff --git a/Makefile b/Makefile | |||||
index 1bf778d..1d0f2bc 100644 | |||||
--- a/Makefile | |||||
+++ b/Makefile | |||||
@@ -301,7 +301,6 @@ ifeq ($(TARGET),osx) | |||||
USE_POLL = implicit | |||||
USE_KQUEUE = implicit | |||||
USE_TPROXY = implicit | |||||
- USE_LIBCRYPT = implicit | |||||
else | |||||
ifeq ($(TARGET),openbsd) | |||||
# This is for OpenBSD >= 3.0 | |||||
diff --git a/src/proto_tcp.c b/src/proto_tcp.c | |||||
index 2c81fb4..4f5d88d 100644 | |||||
--- a/src/proto_tcp.c | |||||
+++ b/src/proto_tcp.c | |||||
@@ -206,7 +206,7 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so | |||||
case AF_INET6: | |||||
if (flags && ip6_transp_working) { | |||||
if (0 | |||||
-#if defined(IPV6_TRANSPARENT) | |||||
+#if defined(IPV6_TRANSPARENT) && defined(SOL_IPV6) | |||||
|| (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == 0) | |||||
#endif | |||||
#if defined(IP_FREEBIND) | |||||
@@ -854,7 +854,7 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen) | |||||
break; | |||||
case AF_INET6: | |||||
if (1 | |||||
-#if defined(IPV6_TRANSPARENT) | |||||
+#if defined(IPV6_TRANSPARENT) && defined(SOL_IPV6) | |||||
&& (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == -1) | |||||
#endif | |||||
#if defined(IP_FREEBIND) | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,31 @@ | |||||
From 3a011f15a8d61cd0088cc0e46743bdc7699db1af Mon Sep 17 00:00:00 2001 | |||||
From: Lukas Tribus <luky-37@hotmail.com> | |||||
Date: Mon, 12 Sep 2016 21:42:00 +0000 | |||||
Subject: [PATCH 02/26] BUG/MINOR: displayed PCRE version is running release | |||||
pcre_version() returns the running PCRE release, not the release | |||||
haproxy was built with. | |||||
This simple string fix should be backported to supported releases, | |||||
as the output may be confusing. | |||||
(cherry picked from commit d64788d9c610163756cac6c91220875e51cba3ef) | |||||
--- | |||||
src/haproxy.c | 2 +- | |||||
1 file changed, 1 insertion(+), 1 deletion(-) | |||||
diff --git a/src/haproxy.c b/src/haproxy.c | |||||
index d70cf63..44d32b9 100644 | |||||
--- a/src/haproxy.c | |||||
+++ b/src/haproxy.c | |||||
@@ -347,7 +347,7 @@ void display_build_opts() | |||||
#endif | |||||
#ifdef USE_PCRE | |||||
- printf("Built with PCRE version : %s", pcre_version()); | |||||
+ printf("Running on PCRE version : %s", pcre_version()); | |||||
printf("\nPCRE library supports JIT : "); | |||||
#ifdef USE_PCRE_JIT | |||||
{ | |||||
-- | |||||
2.7.3 | |||||
@ -1,39 +0,0 @@ | |||||
From fab41521192c6f62f0284faf53d6ad40955ef3db Mon Sep 17 00:00:00 2001 | |||||
From: David CARLIER <devnexen@gmail.com> | |||||
Date: Thu, 24 Mar 2016 09:22:36 +0000 | |||||
Subject: [PATCH 2/4] CLEANUP: connection: fix double negation on memcmp() | |||||
Nothing harmful in here, just clarify that it applies to the whole | |||||
expression. | |||||
(cherry picked from commit 42ff05e2d3d10e8a1e070e66e8883c5eabe196d7) | |||||
(cherry picked from commit c4809151b4c9ccc312cb451e99fd556e867242fc) | |||||
--- | |||||
src/connection.c | 4 ++-- | |||||
1 file changed, 2 insertions(+), 2 deletions(-) | |||||
diff --git a/src/connection.c b/src/connection.c | |||||
index 09fd04e..af18878 100644 | |||||
--- a/src/connection.c | |||||
+++ b/src/connection.c | |||||
@@ -289,7 +289,7 @@ int conn_recv_proxy(struct connection *conn, int flag) | |||||
if (trash.len < 9) /* shortest possible line */ | |||||
goto missing; | |||||
- if (!memcmp(line, "TCP4 ", 5) != 0) { | |||||
+ if (memcmp(line, "TCP4 ", 5) == 0) { | |||||
u32 src3, dst3, sport, dport; | |||||
line += 5; | |||||
@@ -330,7 +330,7 @@ int conn_recv_proxy(struct connection *conn, int flag) | |||||
((struct sockaddr_in *)&conn->addr.to)->sin_port = htons(dport); | |||||
conn->flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET; | |||||
} | |||||
- else if (!memcmp(line, "TCP6 ", 5) != 0) { | |||||
+ else if (memcmp(line, "TCP6 ", 5) == 0) { | |||||
u32 sport, dport; | |||||
char *src_s; | |||||
char *dst_s, *sport_s, *dport_s; | |||||
-- | |||||
2.7.3 | |||||
@ -1,52 +0,0 @@ | |||||
From 294c8d2f81847e0e2d26aa0700564ac2f6aaffa6 Mon Sep 17 00:00:00 2001 | |||||
From: Thierry Fournier <thierry.fournier@ozon.io> | |||||
Date: Mon, 6 Jun 2016 18:28:05 +0200 | |||||
Subject: [PATCH 3/4] BUG/MEDIUM: sticktables: segfault in some configuration | |||||
error cases | |||||
When a stick table is tracked, and another one is used later on the | |||||
configuration, a segfault occurs. | |||||
The function "smp_create_src_stkctr" can return a NULL value, and | |||||
its value is not tested, so one other function try to dereference | |||||
a NULL pointer. This patch just add a verification of the NULL | |||||
pointer. | |||||
The problem is reproduced with this configuration: | |||||
listen www | |||||
mode http | |||||
bind :12345 | |||||
tcp-request content track-sc0 src table IPv4 | |||||
http-request allow if { sc0_inc_gpc0(IPv6) gt 0 } | |||||
server dummy 127.0.0.1:80 | |||||
backend IPv4 | |||||
stick-table type ip size 10 expire 60s store gpc0 | |||||
backend IPv6 | |||||
stick-table type ipv6 size 10 expire 60s store gpc0 | |||||
Thank to kabefuna@gmail.com for the bug report. | |||||
This patch must be backported in the 1.6 and 1.5 version. | |||||
(cherry picked from commit 6fc340ff07171bb85d11d835fa4158bbdef240a0) | |||||
(cherry picked from commit 4693e2302271252044038c9be38487fb16218e5b) | |||||
--- | |||||
src/session.c | 2 +- | |||||
1 file changed, 1 insertion(+), 1 deletion(-) | |||||
diff --git a/src/session.c b/src/session.c | |||||
index 4e84803..fbd5094 100644 | |||||
--- a/src/session.c | |||||
+++ b/src/session.c | |||||
@@ -2908,7 +2908,7 @@ smp_fetch_sc_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned i | |||||
smp->flags = SMP_F_VOL_TEST; | |||||
smp->type = SMP_T_UINT; | |||||
smp->data.uint = 0; | |||||
- if (stkctr_entry(stkctr) != NULL) { | |||||
+ if (stkctr && stkctr_entry(stkctr)) { | |||||
void *ptr; | |||||
/* First, update gpc0_rate if it's tracked. Second, update its | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,49 @@ | |||||
From dcdd2ae7d6809f45c5f6bbe2ba6fe9c70802bb42 Mon Sep 17 00:00:00 2001 | |||||
From: Lukas Tribus <luky-37@hotmail.com> | |||||
Date: Mon, 12 Sep 2016 21:42:07 +0000 | |||||
Subject: [PATCH 03/26] MINOR: show Built with PCRE version | |||||
Inspired by PCRE's pcre_version.c and improved with Willy's | |||||
suggestions. Reusable parts have been added to | |||||
include/common/standard.h. | |||||
(cherry picked from commit dcbc5c5ecf6506b5ad55b98bbec910b29f011f14) | |||||
--- | |||||
include/common/standard.h | 9 +++++++++ | |||||
src/haproxy.c | 3 +++ | |||||
2 files changed, 12 insertions(+) | |||||
diff --git a/include/common/standard.h b/include/common/standard.h | |||||
index 6098550..26a52ff 100644 | |||||
--- a/include/common/standard.h | |||||
+++ b/include/common/standard.h | |||||
@@ -1065,4 +1065,13 @@ static inline void *my_realloc2(void *ptr, size_t size) | |||||
return ret; | |||||
} | |||||
+/* HAP_STRING() makes a string from a literal while HAP_XSTRING() first | |||||
+ * evaluates the argument and is suited to pass macros. | |||||
+ * | |||||
+ * They allow macros like PCRE_MAJOR to be defined without quotes, which | |||||
+ * is convenient for applications that want to test its value. | |||||
+ */ | |||||
+#define HAP_STRING(...) #__VA_ARGS__ | |||||
+#define HAP_XSTRING(...) HAP_STRING(__VA_ARGS__) | |||||
+ | |||||
#endif /* _COMMON_STANDARD_H */ | |||||
diff --git a/src/haproxy.c b/src/haproxy.c | |||||
index 44d32b9..37d700b 100644 | |||||
--- a/src/haproxy.c | |||||
+++ b/src/haproxy.c | |||||
@@ -347,6 +347,9 @@ void display_build_opts() | |||||
#endif | |||||
#ifdef USE_PCRE | |||||
+ printf("Built with PCRE version : %s\n", (HAP_XSTRING(Z PCRE_PRERELEASE)[1] == 0)? | |||||
+ HAP_XSTRING(PCRE_MAJOR.PCRE_MINOR PCRE_DATE) : | |||||
+ HAP_XSTRING(PCRE_MAJOR.PCRE_MINOR) HAP_XSTRING(PCRE_PRERELEASE PCRE_DATE)); | |||||
printf("Running on PCRE version : %s", pcre_version()); | |||||
printf("\nPCRE library supports JIT : "); | |||||
#ifdef USE_PCRE_JIT | |||||
-- | |||||
2.7.3 | |||||
@ -1,32 +0,0 @@ | |||||
From cba3bd6e5ce9b0be83c701c3c7a103d01d5b516d Mon Sep 17 00:00:00 2001 | |||||
From: Thierry Fournier <thierry.fournier@ozon.io> | |||||
Date: Wed, 1 Jun 2016 13:36:20 +0200 | |||||
Subject: [PATCH 4/4] BUG/MINOR: http: add-header: header name copied twice | |||||
The header name is copied two time in the buffer. The first copy is a printf-like | |||||
function writing the name and the http separators in the buffer, and the second | |||||
form is a memcopy. This seems to be inherited from some changes. This patch | |||||
removes the printf like, format. | |||||
This patch must be backported in 1.6 and 1.5 versions | |||||
(cherry picked from commit 53c1a9b7cb8f3fe79b5492218363b6c0ff608fc1) | |||||
(cherry picked from commit d281d68d3aa010f7e1a635c92ab486f7f2c666b9) | |||||
--- | |||||
src/proto_http.c | 1 - | |||||
1 file changed, 1 deletion(-) | |||||
diff --git a/src/proto_http.c b/src/proto_http.c | |||||
index 0b13c5e..8801592 100644 | |||||
--- a/src/proto_http.c | |||||
+++ b/src/proto_http.c | |||||
@@ -3399,7 +3399,6 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct session | |||||
case HTTP_REQ_ACT_SET_HDR: | |||||
case HTTP_REQ_ACT_ADD_HDR: | |||||
- chunk_printf(&trash, "%s: ", rule->arg.hdr_add.name); | |||||
memcpy(trash.str, rule->arg.hdr_add.name, rule->arg.hdr_add.name_len); | |||||
trash.len = rule->arg.hdr_add.name_len; | |||||
trash.str[trash.len++] = ':'; | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,25 @@ | |||||
From 9d59ff222cc81ee356594cfa780349dd91376fd9 Mon Sep 17 00:00:00 2001 | |||||
From: Lukas Tribus <luky-37@hotmail.com> | |||||
Date: Mon, 12 Sep 2016 21:42:14 +0000 | |||||
Subject: [PATCH 04/26] MINOR: show Running on zlib version | |||||
(cherry picked from commit 255cc5184dc8483e4377d9de25670bd6e226cdba) | |||||
--- | |||||
src/haproxy.c | 1 + | |||||
1 file changed, 1 insertion(+) | |||||
diff --git a/src/haproxy.c b/src/haproxy.c | |||||
index 37d700b..9f5878a 100644 | |||||
--- a/src/haproxy.c | |||||
+++ b/src/haproxy.c | |||||
@@ -287,6 +287,7 @@ void display_build_opts() | |||||
#ifdef USE_ZLIB | |||||
printf("Built with zlib version : " ZLIB_VERSION "\n"); | |||||
+ printf("Running on zlib version : %s\n", zlibVersion()); | |||||
#elif defined(USE_SLZ) | |||||
printf("Built with libslz for stateless compression.\n"); | |||||
#else /* USE_ZLIB */ | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,66 @@ | |||||
From 7397526d0c80251b3006b1b45af754f5ad7adb76 Mon Sep 17 00:00:00 2001 | |||||
From: Nenad Merdanovic <nmerdan@anine.io> | |||||
Date: Mon, 3 Oct 2016 04:57:37 +0200 | |||||
Subject: [PATCH 05/26] MINOR: Add fe_req_rate sample fetch | |||||
The fe_req_rate is similar to fe_sess_rate, but fetches the number | |||||
of HTTP requests per second instead of connections/sessions per second. | |||||
Signed-off-by: Nenad Merdanovic <nmerdan@anine.io> | |||||
(cherry picked from commit ad9a7e9770e673a70fb56ab95be18bf88666d92a) | |||||
--- | |||||
doc/configuration.txt | 5 +++++ | |||||
src/frontend.c | 14 ++++++++++++++ | |||||
2 files changed, 19 insertions(+) | |||||
diff --git a/doc/configuration.txt b/doc/configuration.txt | |||||
index d4b1744..d18c399 100644 | |||||
--- a/doc/configuration.txt | |||||
+++ b/doc/configuration.txt | |||||
@@ -12253,6 +12253,11 @@ fe_conn([<frontend>]) : integer | |||||
statistics to servers in HTTP headers. See also the "dst_conn", "be_conn", | |||||
"fe_sess_rate" fetches. | |||||
+fe_req_rate([<frontend>]) : integer | |||||
+ Returns an integer value corresponding to the number of HTTP requests per | |||||
+ second sent to a frontend. This number can differ from "fe_sess_rate" in | |||||
+ situations where client-side keep-alive is enabled. | |||||
+ | |||||
fe_sess_rate([<frontend>]) : integer | |||||
Returns an integer value corresponding to the sessions creation rate on the | |||||
frontend, in number of new sessions per second. This is used with ACLs to | |||||
diff --git a/src/frontend.c b/src/frontend.c | |||||
index 74ec0ab..5cc6202 100644 | |||||
--- a/src/frontend.c | |||||
+++ b/src/frontend.c | |||||
@@ -167,6 +167,19 @@ smp_fetch_fe_id(const struct arg *args, struct sample *smp, const char *kw, void | |||||
return 1; | |||||
} | |||||
+/* set temp integer to the number of HTTP requests per second reaching the frontend. | |||||
+ * Accepts exactly 1 argument. Argument is a frontend, other types will cause | |||||
+ * an undefined behaviour. | |||||
+ */ | |||||
+static int | |||||
+smp_fetch_fe_req_rate(const struct arg *args, struct sample *smp, const char *kw, void *private) | |||||
+{ | |||||
+ smp->flags = SMP_F_VOL_TEST; | |||||
+ smp->data.type = SMP_T_SINT; | |||||
+ smp->data.u.sint = read_freq_ctr(&args->data.prx->fe_req_per_sec); | |||||
+ return 1; | |||||
+} | |||||
+ | |||||
/* set temp integer to the number of connections per second reaching the frontend. | |||||
* Accepts exactly 1 argument. Argument is a frontend, other types will cause | |||||
* an undefined behaviour. | |||||
@@ -200,6 +213,7 @@ smp_fetch_fe_conn(const struct arg *args, struct sample *smp, const char *kw, vo | |||||
static struct sample_fetch_kw_list smp_kws = {ILH, { | |||||
{ "fe_conn", smp_fetch_fe_conn, ARG1(1,FE), NULL, SMP_T_SINT, SMP_USE_INTRN, }, | |||||
{ "fe_id", smp_fetch_fe_id, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, }, | |||||
+ { "fe_req_rate", smp_fetch_fe_req_rate, ARG1(1,FE), NULL, SMP_T_SINT, SMP_USE_INTRN, }, | |||||
{ "fe_sess_rate", smp_fetch_fe_sess_rate, ARG1(1,FE), NULL, SMP_T_SINT, SMP_USE_INTRN, }, | |||||
{ /* END */ }, | |||||
}}; | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,134 @@ | |||||
From 3dd981c016ac7ad636ee546c2b9b685f7e8500d4 Mon Sep 17 00:00:00 2001 | |||||
From: Lukas Tribus <luky-37@hotmail.com> | |||||
Date: Mon, 12 Sep 2016 21:42:20 +0000 | |||||
Subject: [PATCH 06/26] MEDIUM: make SO_REUSEPORT configurable | |||||
With Linux officially introducing SO_REUSEPORT support in 3.9 and | |||||
its mainstream adoption we have seen more people running into strange | |||||
SO_REUSEPORT related issues (a process management issue turning into | |||||
hard to diagnose problems because the kernel load-balances between the | |||||
new and an obsolete haproxy instance). | |||||
Also some people simply want the guarantee that the bind fails when | |||||
the old process is still bound. | |||||
This change makes SO_REUSEPORT configurable, introducing the command | |||||
line argument "-dR" and the noreuseport configuration directive. | |||||
A backport to 1.6 should be considered. | |||||
(cherry picked from commit a0bcbdcb04d52c3ca71045f90aac33d9dd7965bf) | |||||
--- | |||||
doc/configuration.txt | 5 +++++ | |||||
include/types/global.h | 1 + | |||||
src/cfgparse.c | 5 +++++ | |||||
src/haproxy.c | 10 ++++++++++ | |||||
src/proto_tcp.c | 6 +++--- | |||||
5 files changed, 24 insertions(+), 3 deletions(-) | |||||
diff --git a/doc/configuration.txt b/doc/configuration.txt | |||||
index d18c399..e725ce2 100644 | |||||
--- a/doc/configuration.txt | |||||
+++ b/doc/configuration.txt | |||||
@@ -570,6 +570,7 @@ The following keywords are supported in the "global" section : | |||||
- nopoll | |||||
- nosplice | |||||
- nogetaddrinfo | |||||
+ - noreuseport | |||||
- spread-checks | |||||
- server-state-base | |||||
- server-state-file | |||||
@@ -1090,6 +1091,10 @@ nogetaddrinfo | |||||
Disables the use of getaddrinfo(3) for name resolving. It is equivalent to | |||||
the command line argument "-dG". Deprecated gethostbyname(3) will be used. | |||||
+noreuseport | |||||
+ Disables the use of SO_REUSEPORT - see socket(7). It is equivalent to the | |||||
+ command line argument "-dR". | |||||
+ | |||||
spread-checks <0..50, in percent> | |||||
Sometimes it is desirable to avoid sending agent and health checks to | |||||
servers at exact intervals, for instance when many logical servers are | |||||
diff --git a/include/types/global.h b/include/types/global.h | |||||
index 61f0391..2e24d3f 100644 | |||||
--- a/include/types/global.h | |||||
+++ b/include/types/global.h | |||||
@@ -63,6 +63,7 @@ | |||||
/* platform-specific options */ | |||||
#define GTUNE_USE_SPLICE (1<<4) | |||||
#define GTUNE_USE_GAI (1<<5) | |||||
+#define GTUNE_USE_REUSEPORT (1<<6) | |||||
/* Access level for a stats socket */ | |||||
#define ACCESS_LVL_NONE 0 | |||||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||||
index 55086fd..f2a104d 100644 | |||||
--- a/src/cfgparse.c | |||||
+++ b/src/cfgparse.c | |||||
@@ -662,6 +662,11 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm) | |||||
goto out; | |||||
global.tune.options &= ~GTUNE_USE_GAI; | |||||
} | |||||
+ else if (!strcmp(args[0], "noreuseport")) { | |||||
+ if (alertif_too_many_args(0, file, linenum, args, &err_code)) | |||||
+ goto out; | |||||
+ global.tune.options &= ~GTUNE_USE_REUSEPORT; | |||||
+ } | |||||
else if (!strcmp(args[0], "quiet")) { | |||||
if (alertif_too_many_args(0, file, linenum, args, &err_code)) | |||||
goto out; | |||||
diff --git a/src/haproxy.c b/src/haproxy.c | |||||
index 9f5878a..a657dc4 100644 | |||||
--- a/src/haproxy.c | |||||
+++ b/src/haproxy.c | |||||
@@ -452,6 +452,9 @@ void usage(char *name) | |||||
#if defined(USE_GETADDRINFO) | |||||
" -dG disables getaddrinfo() usage\n" | |||||
#endif | |||||
+#if defined(SO_REUSEPORT) | |||||
+ " -dR disables SO_REUSEPORT usage\n" | |||||
+#endif | |||||
" -dV disables SSL verify on servers side\n" | |||||
" -sf/-st [pid ]* finishes/terminates old pids.\n" | |||||
"\n", | |||||
@@ -623,6 +626,9 @@ void init(int argc, char **argv) | |||||
#if defined(USE_GETADDRINFO) | |||||
global.tune.options |= GTUNE_USE_GAI; | |||||
#endif | |||||
+#if defined(SO_REUSEPORT) | |||||
+ global.tune.options |= GTUNE_USE_REUSEPORT; | |||||
+#endif | |||||
pid = getpid(); | |||||
progname = *argv; | |||||
@@ -666,6 +672,10 @@ void init(int argc, char **argv) | |||||
else if (*flag == 'd' && flag[1] == 'G') | |||||
global.tune.options &= ~GTUNE_USE_GAI; | |||||
#endif | |||||
+#if defined(SO_REUSEPORT) | |||||
+ else if (*flag == 'd' && flag[1] == 'R') | |||||
+ global.tune.options &= ~GTUNE_USE_REUSEPORT; | |||||
+#endif | |||||
else if (*flag == 'd' && flag[1] == 'V') | |||||
global.ssl_server_verify = SSL_SERVER_VERIFY_NONE; | |||||
else if (*flag == 'V') | |||||
diff --git a/src/proto_tcp.c b/src/proto_tcp.c | |||||
index 4f5d88d..0f20fde 100644 | |||||
--- a/src/proto_tcp.c | |||||
+++ b/src/proto_tcp.c | |||||
@@ -824,10 +824,10 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen) | |||||
setsockopt(fd, SOL_SOCKET, SO_LINGER, &nolinger, sizeof(struct linger)); | |||||
#ifdef SO_REUSEPORT | |||||
- /* OpenBSD supports this. As it's present in old libc versions of Linux, | |||||
- * it might return an error that we will silently ignore. | |||||
+ /* OpenBSD and Linux 3.9 support this. As it's present in old libc versions of | |||||
+ * Linux, it might return an error that we will silently ignore. | |||||
*/ | |||||
- if (!ext) | |||||
+ if (!ext && (global.tune.options & GTUNE_USE_REUSEPORT)) | |||||
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); | |||||
#endif | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,29 @@ | |||||
From 21877a43afd6300518140c415ccec2dba0a0591f Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Fri, 21 Oct 2016 17:13:24 +0200 | |||||
Subject: [PATCH 07/26] BUG/MINOR: vars: use sess and not s->sess in | |||||
action_store() | |||||
This causes the stream to be dereferenced when not needed. It will | |||||
cause trouble when variables are used outside of a stream. | |||||
(cherry picked from commit 108a8fd8be0c78a4bf147a2028fd9bda3343c93c) | |||||
--- | |||||
src/vars.c | 2 +- | |||||
1 file changed, 1 insertion(+), 1 deletion(-) | |||||
diff --git a/src/vars.c b/src/vars.c | |||||
index 56fade5..b22c3bf 100644 | |||||
--- a/src/vars.c | |||||
+++ b/src/vars.c | |||||
@@ -507,7 +507,7 @@ static enum act_return action_store(struct act_rule *rule, struct proxy *px, | |||||
/* Process the expression. */ | |||||
memset(&smp, 0, sizeof(smp)); | |||||
- if (!sample_process(px, s->sess, s, dir|SMP_OPT_FINAL, | |||||
+ if (!sample_process(px, sess, s, dir|SMP_OPT_FINAL, | |||||
rule->arg.vars.expr, &smp)) | |||||
return ACT_RET_CONT; | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,47 @@ | |||||
From ff403602edc917b8bef2062dc0d5dec2017e3232 Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Fri, 21 Oct 2016 17:14:35 +0200 | |||||
Subject: [PATCH 08/26] BUG/MINOR: vars: make smp_fetch_var() more robust | |||||
against misuses | |||||
smp_fetch_var() may be called from everywhere since it just reads a | |||||
variable. It must ensure that the stream exists before trying to return | |||||
a stream-dependant variable. For now there is no impact but it will | |||||
cause trouble with tcp-request session rules. | |||||
(cherry picked from commit 7513d001c8a6b7d1cf8e7d5469942cd39d6e8160) | |||||
--- | |||||
src/vars.c | 16 +++++++++++++--- | |||||
1 file changed, 13 insertions(+), 3 deletions(-) | |||||
diff --git a/src/vars.c b/src/vars.c | |||||
index b22c3bf..4a0c4ed 100644 | |||||
--- a/src/vars.c | |||||
+++ b/src/vars.c | |||||
@@ -242,11 +242,21 @@ static int smp_fetch_var(const struct arg *args, struct sample *smp, const char | |||||
/* Check the availibity of the variable. */ | |||||
switch (var_desc->scope) { | |||||
- case SCOPE_SESS: vars = &smp->sess->vars; break; | |||||
- case SCOPE_TXN: vars = &smp->strm->vars_txn; break; | |||||
+ case SCOPE_SESS: | |||||
+ vars = &smp->sess->vars; | |||||
+ break; | |||||
+ case SCOPE_TXN: | |||||
+ if (!smp->strm) | |||||
+ return 0; | |||||
+ vars = &smp->strm->vars_txn; | |||||
+ break; | |||||
case SCOPE_REQ: | |||||
case SCOPE_RES: | |||||
- default: vars = &smp->strm->vars_reqres; break; | |||||
+ default: | |||||
+ if (!smp->strm) | |||||
+ return 0; | |||||
+ vars = &smp->strm->vars_reqres; | |||||
+ break; | |||||
} | |||||
if (vars->scope != var_desc->scope) | |||||
return 0; | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,31 @@ | |||||
From 3810ab9e71a19e7f04a9e18580abc77c276d0ff1 Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Fri, 21 Oct 2016 17:17:18 +0200 | |||||
Subject: [PATCH 09/26] BUG/MINOR: vars: smp_fetch_var() doesn't depend on HTTP | |||||
but on the session | |||||
Thus the SMP_USE_HTTP_ANY dependency is incorrect, we have to depend on | |||||
SMP_USE_L5_CLI (the session). It's particularly important for session-wide | |||||
variables which are kept across HTTP requests. For now there is no impact | |||||
but it will make a difference with tcp-request session rules. | |||||
(cherry picked from commit 87846e42a478fe2aa0fbc1e162ba5fb227be49b7) | |||||
--- | |||||
src/vars.c | 2 +- | |||||
1 file changed, 1 insertion(+), 1 deletion(-) | |||||
diff --git a/src/vars.c b/src/vars.c | |||||
index 4a0c4ed..a3dd85c 100644 | |||||
--- a/src/vars.c | |||||
+++ b/src/vars.c | |||||
@@ -654,7 +654,7 @@ static int vars_max_size_reqres(char **args, int section_type, struct proxy *cur | |||||
static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { | |||||
- { "var", smp_fetch_var, ARG1(1,STR), smp_check_var, SMP_T_STR, SMP_USE_HTTP_ANY }, | |||||
+ { "var", smp_fetch_var, ARG1(1,STR), smp_check_var, SMP_T_STR, SMP_USE_L5CLI }, | |||||
{ /* END */ }, | |||||
}}; | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,29 @@ | |||||
From 2d7ed4ae91383cd35fe07cd34d01c23b4a5d03f5 Mon Sep 17 00:00:00 2001 | |||||
From: "Thierry FOURNIER / OZON.IO" <thierry.fournier@ozon.io> | |||||
Date: Thu, 6 Oct 2016 10:35:29 +0200 | |||||
Subject: [PATCH 10/26] BUG/MINOR: ssl: Check malloc return code | |||||
If malloc() can't allocate memory and return NULL, a segfaut will raises. | |||||
This patch should be backported in the 1.6 and 1.5 version. | |||||
(cherry picked from commit 7a3bd3b9dc43509bb1869389dcf91e35c0155f9b) | |||||
--- | |||||
src/ssl_sock.c | 2 ++ | |||||
1 file changed, 2 insertions(+) | |||||
diff --git a/src/ssl_sock.c b/src/ssl_sock.c | |||||
index 0535a3b..5f9a203 100644 | |||||
--- a/src/ssl_sock.c | |||||
+++ b/src/ssl_sock.c | |||||
@@ -1572,6 +1572,8 @@ static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, | |||||
int j, len; | |||||
len = strlen(name); | |||||
sc = malloc(sizeof(struct sni_ctx) + len + 1); | |||||
+ if (!sc) | |||||
+ return order; | |||||
for (j = 0; j < len; j++) | |||||
sc->name.key[j] = tolower(name[j]); | |||||
sc->name.key[len] = 0; | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,70 @@ | |||||
From b2b0eab46a8ae36f2dd49159e65c90c1089a0f96 Mon Sep 17 00:00:00 2001 | |||||
From: "Thierry FOURNIER / OZON.IO" <thierry.fournier@ozon.io> | |||||
Date: Thu, 6 Oct 2016 10:56:48 +0200 | |||||
Subject: [PATCH 11/26] BUG/MINOR: ssl: prevent multiple entries for the same | |||||
certificate | |||||
Today, the certificate are indexed int he SNI tree using their CN and the | |||||
list of thier AltNames. So, Some certificates have the same names in the | |||||
CN and one of the AltNames entries. | |||||
Typically Let's Encrypt duplicate the the DNS name in the CN and the | |||||
AltName. | |||||
This patch prevents the creation of identical entries in the trees. It | |||||
checks the same DNS name and the same SSL context. | |||||
If the same certificate is registered two time it will be duplicated. | |||||
This patch should be backported in the 1.6 and 1.5 version. | |||||
(cherry picked from commit 07c3d78c2c0693ee37db71c34723597638b6ab3f) | |||||
--- | |||||
src/ssl_sock.c | 22 +++++++++++++++++++--- | |||||
1 file changed, 19 insertions(+), 3 deletions(-) | |||||
diff --git a/src/ssl_sock.c b/src/ssl_sock.c | |||||
index 5f9a203..ad8054d 100644 | |||||
--- a/src/ssl_sock.c | |||||
+++ b/src/ssl_sock.c | |||||
@@ -1556,6 +1556,7 @@ static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, | |||||
{ | |||||
struct sni_ctx *sc; | |||||
int wild = 0, neg = 0; | |||||
+ struct ebmb_node *node; | |||||
if (*name == '!') { | |||||
neg = 1; | |||||
@@ -1571,12 +1572,27 @@ static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, | |||||
if (*name) { | |||||
int j, len; | |||||
len = strlen(name); | |||||
+ for (j = 0; j < len && j < trash.size; j++) | |||||
+ trash.str[j] = tolower(name[j]); | |||||
+ if (j >= trash.size) | |||||
+ return order; | |||||
+ trash.str[j] = 0; | |||||
+ | |||||
+ /* Check for duplicates. */ | |||||
+ if (wild) | |||||
+ node = ebst_lookup(&s->sni_w_ctx, trash.str); | |||||
+ else | |||||
+ node = ebst_lookup(&s->sni_ctx, trash.str); | |||||
+ for (; node; node = ebmb_next_dup(node)) { | |||||
+ sc = ebmb_entry(node, struct sni_ctx, name); | |||||
+ if (sc->ctx == ctx && sc->neg == neg) | |||||
+ return order; | |||||
+ } | |||||
+ | |||||
sc = malloc(sizeof(struct sni_ctx) + len + 1); | |||||
if (!sc) | |||||
return order; | |||||
- for (j = 0; j < len; j++) | |||||
- sc->name.key[j] = tolower(name[j]); | |||||
- sc->name.key[len] = 0; | |||||
+ memcpy(sc->name.key, trash.str, len + 1); | |||||
sc->ctx = ctx; | |||||
sc->order = order++; | |||||
sc->neg = neg; | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,31 @@ | |||||
From 03c706d71e2d314670d2ebb4dfa48fd3b793b361 Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Tue, 25 Oct 2016 15:50:47 +0200 | |||||
Subject: [PATCH 12/26] BUG/MINOR: systemd: make the wrapper return a non-null | |||||
status code on error | |||||
When execv() fails to execute the haproxy executable, it's important to | |||||
return an error instead of pretending everything is cool. This fix should | |||||
be backported to 1.6 and 1.5 in order to improve the overall reliability | |||||
under systemd. | |||||
(cherry picked from commit 7643d09dca4d0eed97ba3c29d4f4fd1f037f96ae) | |||||
--- | |||||
src/haproxy-systemd-wrapper.c | 2 +- | |||||
1 file changed, 1 insertion(+), 1 deletion(-) | |||||
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c | |||||
index d118ec6..a78e75b 100644 | |||||
--- a/src/haproxy-systemd-wrapper.c | |||||
+++ b/src/haproxy-systemd-wrapper.c | |||||
@@ -94,7 +94,7 @@ static void spawn_haproxy(char **pid_strv, int nb_pid) | |||||
fprintf(stderr, "\n"); | |||||
execv(argv[0], argv); | |||||
- exit(0); | |||||
+ exit(1); | |||||
} | |||||
} | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,117 @@ | |||||
From 7a7eada6f4ecfc54325a18cf20c3035994a901c4 Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Tue, 25 Oct 2016 16:49:31 +0200 | |||||
Subject: [PATCH 13/26] BUG/MINOR: systemd: always restore signals before | |||||
execve() | |||||
Since signals are inherited, we must restore them before calling execve() | |||||
and intercept them again after a failed execve(). In order to cleanly deal | |||||
with the SIGUSR2/SIGHUP loops where we re-exec the wrapper, we ignore these | |||||
two signals during a re-exec, and restore them to defaults when spawning | |||||
haproxy. | |||||
This should be backported to 1.6 and 1.5. | |||||
(cherry picked from commit 4351ea61fbddf88c960179d60b0e0f1b090f0b70) | |||||
--- | |||||
src/haproxy-systemd-wrapper.c | 49 ++++++++++++++++++++++++++++++++++++------- | |||||
1 file changed, 41 insertions(+), 8 deletions(-) | |||||
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c | |||||
index a78e75b..84d2e17 100644 | |||||
--- a/src/haproxy-systemd-wrapper.c | |||||
+++ b/src/haproxy-systemd-wrapper.c | |||||
@@ -28,6 +28,11 @@ static char *pid_file = "/run/haproxy.pid"; | |||||
static int wrapper_argc; | |||||
static char **wrapper_argv; | |||||
+static void setup_signal_handler(); | |||||
+static void pause_signal_handler(); | |||||
+static void reset_signal_handler(); | |||||
+ | |||||
+ | |||||
/* returns the path to the haproxy binary into <buffer>, whose size indicated | |||||
* in <buffer_size> must be at least 1 byte long. | |||||
*/ | |||||
@@ -76,6 +81,8 @@ static void spawn_haproxy(char **pid_strv, int nb_pid) | |||||
char **argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *)); | |||||
int i; | |||||
int argno = 0; | |||||
+ | |||||
+ reset_signal_handler(); | |||||
locate_haproxy(haproxy_bin, 512); | |||||
argv[argno++] = haproxy_bin; | |||||
for (i = 0; i < main_argc; ++i) | |||||
@@ -127,6 +134,34 @@ static void signal_handler(int signum) | |||||
caught_signal = signum; | |||||
} | |||||
+static void setup_signal_handler() | |||||
+{ | |||||
+ struct sigaction sa; | |||||
+ | |||||
+ memset(&sa, 0, sizeof(struct sigaction)); | |||||
+ sa.sa_handler = &signal_handler; | |||||
+ sigaction(SIGUSR2, &sa, NULL); | |||||
+ sigaction(SIGHUP, &sa, NULL); | |||||
+ sigaction(SIGINT, &sa, NULL); | |||||
+ sigaction(SIGTERM, &sa, NULL); | |||||
+} | |||||
+ | |||||
+static void pause_signal_handler() | |||||
+{ | |||||
+ signal(SIGUSR2, SIG_IGN); | |||||
+ signal(SIGHUP, SIG_IGN); | |||||
+ signal(SIGINT, SIG_DFL); | |||||
+ signal(SIGTERM, SIG_DFL); | |||||
+} | |||||
+ | |||||
+static void reset_signal_handler() | |||||
+{ | |||||
+ signal(SIGUSR2, SIG_DFL); | |||||
+ signal(SIGHUP, SIG_DFL); | |||||
+ signal(SIGINT, SIG_DFL); | |||||
+ signal(SIGTERM, SIG_DFL); | |||||
+} | |||||
+ | |||||
/* handles SIGUSR2 and SIGHUP only */ | |||||
static void do_restart(int sig) | |||||
{ | |||||
@@ -134,7 +169,11 @@ static void do_restart(int sig) | |||||
fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: re-executing on %s.\n", | |||||
sig == SIGUSR2 ? "SIGUSR2" : "SIGHUP"); | |||||
+ /* don't let the other process take one of those signals by accident */ | |||||
+ pause_signal_handler(); | |||||
execv(wrapper_argv[0], wrapper_argv); | |||||
+ /* failed, let's reinstall the signal handler and continue */ | |||||
+ setup_signal_handler(); | |||||
} | |||||
/* handles SIGTERM and SIGINT only */ | |||||
@@ -168,7 +207,8 @@ static void init(int argc, char **argv) | |||||
int main(int argc, char **argv) | |||||
{ | |||||
int status; | |||||
- struct sigaction sa; | |||||
+ | |||||
+ setup_signal_handler(); | |||||
wrapper_argc = argc; | |||||
wrapper_argv = argv; | |||||
@@ -176,13 +216,6 @@ int main(int argc, char **argv) | |||||
--argc; ++argv; | |||||
init(argc, argv); | |||||
- memset(&sa, 0, sizeof(struct sigaction)); | |||||
- sa.sa_handler = &signal_handler; | |||||
- sigaction(SIGUSR2, &sa, NULL); | |||||
- sigaction(SIGHUP, &sa, NULL); | |||||
- sigaction(SIGINT, &sa, NULL); | |||||
- sigaction(SIGTERM, &sa, NULL); | |||||
- | |||||
if (getenv(REEXEC_FLAG) != NULL) { | |||||
/* We are being re-executed: restart HAProxy gracefully */ | |||||
int i; | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,41 @@ | |||||
From 106cb89907ea6eab0073708bb8d6f56d7fc64509 Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Tue, 25 Oct 2016 17:05:56 +0200 | |||||
Subject: [PATCH 14/26] BUG/MINOR: systemd: check return value of calloc() | |||||
The wrapper is not the best reliable thing in the universe, so start | |||||
by adding at least the minimum expected controls :-/ | |||||
To be backported to 1.5 and 1.6. | |||||
(cherry picked from commit 3747ea07ce6b647b86559383f7d09b42550d42f3) | |||||
--- | |||||
src/haproxy-systemd-wrapper.c | 10 ++++++++-- | |||||
1 file changed, 8 insertions(+), 2 deletions(-) | |||||
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c | |||||
index 84d2e17..15c48ca 100644 | |||||
--- a/src/haproxy-systemd-wrapper.c | |||||
+++ b/src/haproxy-systemd-wrapper.c | |||||
@@ -77,11 +77,17 @@ static void spawn_haproxy(char **pid_strv, int nb_pid) | |||||
pid = fork(); | |||||
if (!pid) { | |||||
- /* 3 for "haproxy -Ds -sf" */ | |||||
- char **argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *)); | |||||
+ char **argv; | |||||
int i; | |||||
int argno = 0; | |||||
+ /* 3 for "haproxy -Ds -sf" */ | |||||
+ argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *)); | |||||
+ if (!argv) { | |||||
+ fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: failed to calloc(), please try again later.\n"); | |||||
+ exit(1); | |||||
+ } | |||||
+ | |||||
reset_signal_handler(); | |||||
locate_haproxy(haproxy_bin, 512); | |||||
argv[argno++] = haproxy_bin; | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,41 @@ | |||||
From 3bc0a399d2875e9e0627a70906c1403eef60ec60 Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Tue, 25 Oct 2016 16:51:40 +0200 | |||||
Subject: [PATCH 15/26] MINOR: systemd: report it when execve() fails | |||||
It's important to know that a signal sent to the wrapper had no effect | |||||
because something failed during execve(). Ideally more info (strerror) | |||||
should be reported. It would be nice to backport this to 1.6 and 1.5. | |||||
(cherry picked from commit a785269b4e09114224062081f02b443b6008c524) | |||||
--- | |||||
src/haproxy-systemd-wrapper.c | 5 +++++ | |||||
1 file changed, 5 insertions(+) | |||||
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c | |||||
index 15c48ca..f4fcab1 100644 | |||||
--- a/src/haproxy-systemd-wrapper.c | |||||
+++ b/src/haproxy-systemd-wrapper.c | |||||
@@ -107,8 +107,12 @@ static void spawn_haproxy(char **pid_strv, int nb_pid) | |||||
fprintf(stderr, "\n"); | |||||
execv(argv[0], argv); | |||||
+ fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: execv(%s) failed, please try again later.\n", argv[0]); | |||||
exit(1); | |||||
} | |||||
+ else if (pid == -1) { | |||||
+ fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: failed to fork(), please try again later.\n"); | |||||
+ } | |||||
} | |||||
static int read_pids(char ***pid_strv) | |||||
@@ -180,6 +184,7 @@ static void do_restart(int sig) | |||||
execv(wrapper_argv[0], wrapper_argv); | |||||
/* failed, let's reinstall the signal handler and continue */ | |||||
setup_signal_handler(); | |||||
+ fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: re-exec(%s) failed.\n", wrapper_argv[0]); | |||||
} | |||||
/* handles SIGTERM and SIGINT only */ | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,144 @@ | |||||
From ff81ac47267c4e0227d1e3fbc5b1dedfd81a2a2f Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Tue, 25 Oct 2016 17:20:24 +0200 | |||||
Subject: [PATCH 16/26] BUG/MEDIUM: systemd: let the wrapper know that haproxy | |||||
has completed or failed | |||||
Pierre Cheynier found that there's a persistent issue with the systemd | |||||
wrapper. Too fast reloads can lead to certain old processes not being | |||||
signaled at all and continuing to run. The problem was tracked down as | |||||
a race between the startup and the signal processing : nothing prevents | |||||
the wrapper from starting new processes while others are still starting, | |||||
and the resulting pid file will only contain the latest pids in this | |||||
case. This can happen with large configs and/or when a lot of SSL | |||||
certificates are involved. | |||||
In order to solve this we want the wrapper to wait for the new processes | |||||
to complete their startup. But we also want to ensure it doesn't wait for | |||||
nothing in case of error. | |||||
The solution found here is to create a pipe between the wrapper and the | |||||
sub-processes. The wrapper waits on the pipe and the sub-processes are | |||||
expected to close this pipe once they completed their startup. That way | |||||
we don't queue up new processes until the previous ones have registered | |||||
their pids to the pid file. And if anything goes wrong, the wrapper is | |||||
immediately released. The only thing is that we need the sub-processes | |||||
to know the pipe's file descriptor. We pass it in an environment variable | |||||
called HAPROXY_WRAPPER_FD. | |||||
It was confirmed both by Pierre and myself that this completely solves | |||||
the "zombie" process issue so that only the new processes continue to | |||||
listen on the sockets. | |||||
It seems that in the future this stuff could be moved to the haproxy | |||||
master process, also getting rid of an environment variable. | |||||
This fix needs to be backported to 1.6 and 1.5. | |||||
(cherry picked from commit b957109727f7fed556c049d40bacf45f0df211db) | |||||
--- | |||||
src/haproxy-systemd-wrapper.c | 36 ++++++++++++++++++++++++++++++++++++ | |||||
src/haproxy.c | 10 ++++++++++ | |||||
2 files changed, 46 insertions(+) | |||||
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c | |||||
index f4fcab1..b426f96 100644 | |||||
--- a/src/haproxy-systemd-wrapper.c | |||||
+++ b/src/haproxy-systemd-wrapper.c | |||||
@@ -65,16 +65,30 @@ static void locate_haproxy(char *buffer, size_t buffer_size) | |||||
return; | |||||
} | |||||
+/* Note: this function must not exit in case of error (except in the child), as | |||||
+ * it is only dedicated the starting a new haproxy process. By keeping the | |||||
+ * process alive it will ensure that future signal delivery may get rid of | |||||
+ * the issue. If the first startup fails, the wrapper will notice it and | |||||
+ * return an error thanks to wait() returning ECHILD. | |||||
+ */ | |||||
static void spawn_haproxy(char **pid_strv, int nb_pid) | |||||
{ | |||||
char haproxy_bin[512]; | |||||
pid_t pid; | |||||
int main_argc; | |||||
char **main_argv; | |||||
+ int pipefd[2]; | |||||
+ char fdstr[20]; | |||||
+ int ret; | |||||
main_argc = wrapper_argc - 1; | |||||
main_argv = wrapper_argv + 1; | |||||
+ if (pipe(pipefd) != 0) { | |||||
+ fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: failed to create a pipe, please try again later.\n"); | |||||
+ return; | |||||
+ } | |||||
+ | |||||
pid = fork(); | |||||
if (!pid) { | |||||
char **argv; | |||||
@@ -89,6 +103,15 @@ static void spawn_haproxy(char **pid_strv, int nb_pid) | |||||
} | |||||
reset_signal_handler(); | |||||
+ | |||||
+ close(pipefd[0]); /* close the read side */ | |||||
+ | |||||
+ snprintf(fdstr, sizeof(fdstr), "%d", pipefd[1]); | |||||
+ if (setenv("HAPROXY_WRAPPER_FD", fdstr, 1) != 0) { | |||||
+ fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: failed to setenv(), please try again later.\n"); | |||||
+ exit(1); | |||||
+ } | |||||
+ | |||||
locate_haproxy(haproxy_bin, 512); | |||||
argv[argno++] = haproxy_bin; | |||||
for (i = 0; i < main_argc; ++i) | |||||
@@ -113,6 +136,19 @@ static void spawn_haproxy(char **pid_strv, int nb_pid) | |||||
else if (pid == -1) { | |||||
fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: failed to fork(), please try again later.\n"); | |||||
} | |||||
+ | |||||
+ /* The parent closes the write side and waits for the child to close it | |||||
+ * as well. Also deal the case where the fd would unexpectedly be 1 or 2 | |||||
+ * by silently draining all data. | |||||
+ */ | |||||
+ close(pipefd[1]); | |||||
+ | |||||
+ do { | |||||
+ char c; | |||||
+ ret = read(pipefd[0], &c, sizeof(c)); | |||||
+ } while ((ret > 0) || (ret == -1 && errno == EINTR)); | |||||
+ /* the child has finished starting up */ | |||||
+ close(pipefd[0]); | |||||
} | |||||
static int read_pids(char ***pid_strv) | |||||
diff --git a/src/haproxy.c b/src/haproxy.c | |||||
index a657dc4..2d476f2 100644 | |||||
--- a/src/haproxy.c | |||||
+++ b/src/haproxy.c | |||||
@@ -1843,6 +1843,7 @@ int main(int argc, char **argv) | |||||
int ret = 0; | |||||
int *children = calloc(global.nbproc, sizeof(int)); | |||||
int proc; | |||||
+ char *wrapper_fd; | |||||
/* the father launches the required number of processes */ | |||||
for (proc = 0; proc < global.nbproc; proc++) { | |||||
@@ -1879,6 +1880,15 @@ int main(int argc, char **argv) | |||||
close(pidfd); | |||||
} | |||||
+ /* each child must notify the wrapper that it's ready by closing the requested fd */ | |||||
+ wrapper_fd = getenv("HAPROXY_WRAPPER_FD"); | |||||
+ if (wrapper_fd) { | |||||
+ int pipe_fd = atoi(wrapper_fd); | |||||
+ | |||||
+ if (pipe_fd >= 0) | |||||
+ close(pipe_fd); | |||||
+ } | |||||
+ | |||||
/* We won't ever use this anymore */ | |||||
free(oldpids); oldpids = NULL; | |||||
free(global.chroot); global.chroot = NULL; | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,32 @@ | |||||
From 4fc2ce4a4bb83862679e40c09c684dbf266099f2 Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Wed, 10 Aug 2016 18:24:48 +0200 | |||||
Subject: [PATCH 17/26] BUILD: protocol: fix some build errors on OpenBSD | |||||
Building 1.6 and above on OpenBSD 5.2 fails due to protocol.c not | |||||
including sys/types.h before sys/socket.h : | |||||
In file included from src/protocol.c:14: | |||||
/usr/include/sys/socket.h:162: error: expected specifier-qualifier-list before 'u_int8_t' | |||||
This fix needs to be backported to 1.6. | |||||
(cherry picked from commit a6e3be7ae977ba907ec6ed028c5ab50a6a51886a) | |||||
--- | |||||
src/protocol.c | 1 + | |||||
1 file changed, 1 insertion(+) | |||||
diff --git a/src/protocol.c b/src/protocol.c | |||||
index 3caccb6..7884ef7 100644 | |||||
--- a/src/protocol.c | |||||
+++ b/src/protocol.c | |||||
@@ -10,6 +10,7 @@ | |||||
* | |||||
*/ | |||||
+#include <sys/types.h> | |||||
#include <sys/socket.h> | |||||
#include <common/config.h> | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,32 @@ | |||||
From 27f28950d4f9e44e776db5a5d2bc8d07df45eb30 Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Wed, 10 Aug 2016 18:30:56 +0200 | |||||
Subject: [PATCH 18/26] BUILD: log: iovec requires to include sys/uio.h on | |||||
OpenBSD | |||||
The following commit merged into 1.6-dev6 broke the build on OpenBSD : | |||||
609ac2a ("MEDIUM: log: replace sendto() with sendmsg() in __send_log()") | |||||
Including sys/uio.h is enough to fix this. This fix needs to be backported | |||||
to 1.6. | |||||
(cherry picked from commit 077edcba2e5c25524b720f905417d9f0616cd252) | |||||
--- | |||||
src/log.c | 1 + | |||||
1 file changed, 1 insertion(+) | |||||
diff --git a/src/log.c b/src/log.c | |||||
index 1ddc06d..293a034 100644 | |||||
--- a/src/log.c | |||||
+++ b/src/log.c | |||||
@@ -22,6 +22,7 @@ | |||||
#include <errno.h> | |||||
#include <sys/time.h> | |||||
+#include <sys/uio.h> | |||||
#include <common/config.h> | |||||
#include <common/compat.h> | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,32 @@ | |||||
From 2a63a2b7e32bba4a33c5f4081647124565929f6a Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Wed, 10 Aug 2016 18:42:17 +0200 | |||||
Subject: [PATCH 19/26] BUILD: tcp: do not include netinet/ip.h for IP_TTL | |||||
On OpenBSD, netinet/ip.h fails unless in_systm.h is included. This | |||||
include was added by the silent-drop feature introduced with commit | |||||
2d392c2 ("MEDIUM: tcp: add new tcp action "silent-drop"") in 1.6-dev6, | |||||
but we don't need it, IP_TTL is defined in netinet/in.h, so let's drop | |||||
this useless include. | |||||
This fix needs to be backported to 1.6. | |||||
(cherry picked from commit 7f3e3c0159401cdf47575bc82304696b3a98a2ab) | |||||
--- | |||||
src/proto_tcp.c | 1 - | |||||
1 file changed, 1 deletion(-) | |||||
diff --git a/src/proto_tcp.c b/src/proto_tcp.c | |||||
index 0f20fde..83b862a 100644 | |||||
--- a/src/proto_tcp.c | |||||
+++ b/src/proto_tcp.c | |||||
@@ -31,7 +31,6 @@ | |||||
#include <netinet/tcp.h> | |||||
#include <netinet/in.h> | |||||
-#include <netinet/ip.h> | |||||
#include <common/cfgparse.h> | |||||
#include <common/compat.h> | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,48 @@ | |||||
From a581cf03110f13c61faeaf87efa5b4e2777087d0 Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Wed, 10 Aug 2016 19:29:09 +0200 | |||||
Subject: [PATCH 20/26] BUILD: checks: remove the last strcat and eliminate a | |||||
warning on OpenBSD | |||||
OpenBSD emits warnings on usages of strcpy, strcat and sprintf (and | |||||
probably a few others). Here we have a single such warning in all the code | |||||
reintroduced by commit 0ba0e4a ("MEDIUM: Support sending email alerts") in | |||||
1.6-dev1. Let's get rid of it, the open-coding of strcat is as small as its | |||||
usage and the the result is even more efficient. | |||||
This fix needs to be backported to 1.6. | |||||
(cherry picked from commit 64345aaaf0dc2739983902cce4667089ad926a49) | |||||
--- | |||||
src/checks.c | 7 +++++-- | |||||
1 file changed, 5 insertions(+), 2 deletions(-) | |||||
diff --git a/src/checks.c b/src/checks.c | |||||
index 80b2fc3..55c13a9 100644 | |||||
--- a/src/checks.c | |||||
+++ b/src/checks.c | |||||
@@ -3164,6 +3164,8 @@ static int add_tcpcheck_expect_str(struct list *list, const char *str) | |||||
static int add_tcpcheck_send_strs(struct list *list, const char * const *strs) | |||||
{ | |||||
struct tcpcheck_rule *tcpcheck; | |||||
+ const char *in; | |||||
+ char *dst; | |||||
int i; | |||||
tcpcheck = calloc(1, sizeof *tcpcheck); | |||||
@@ -3181,10 +3183,11 @@ static int add_tcpcheck_send_strs(struct list *list, const char * const *strs) | |||||
free(tcpcheck); | |||||
return 0; | |||||
} | |||||
- tcpcheck->string[0] = '\0'; | |||||
+ dst = tcpcheck->string; | |||||
for (i = 0; strs[i]; i++) | |||||
- strcat(tcpcheck->string, strs[i]); | |||||
+ for (in = strs[i]; (*dst = *in++); dst++); | |||||
+ *dst = 0; | |||||
LIST_ADDQ(list, &tcpcheck->list); | |||||
return 1; | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,39 @@ | |||||
From a19f5bfb0d1e606dc2eb80af903c229ca41d5057 Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Wed, 10 Aug 2016 21:21:57 +0200 | |||||
Subject: [PATCH 21/26] BUILD: poll: remove unused hap_fd_isset() which causes | |||||
a warning with clang | |||||
Clang reports that this function is not used : | |||||
src/ev_poll.c:34:28: warning: unused function 'hap_fd_isset' [-Wunused-function] | |||||
static inline unsigned int hap_fd_isset(int fd, unsigned int *evts) | |||||
It's been true since the rework of the pollers in 1.5 and it's unlikely we'll | |||||
ever need it anymore, so better remove it now to provide clean builds. | |||||
This fix can be backported to 1.6 and 1.5 now. | |||||
(cherry picked from commit 091e86e1ee8ec51bd5a3c1935666a822a51b9051) | |||||
--- | |||||
src/ev_poll.c | 5 ----- | |||||
1 file changed, 5 deletions(-) | |||||
diff --git a/src/ev_poll.c b/src/ev_poll.c | |||||
index 44a2b9b..80d88eb 100644 | |||||
--- a/src/ev_poll.c | |||||
+++ b/src/ev_poll.c | |||||
@@ -31,11 +31,6 @@ static unsigned int *fd_evts[2]; | |||||
static struct pollfd *poll_events = NULL; | |||||
-static inline unsigned int hap_fd_isset(int fd, unsigned int *evts) | |||||
-{ | |||||
- return evts[fd / (8*sizeof(*evts))] & (1U << (fd & (8*sizeof(*evts) - 1))); | |||||
-} | |||||
- | |||||
static inline void hap_fd_set(int fd, unsigned int *evts) | |||||
{ | |||||
evts[fd / (8*sizeof(*evts))] |= 1U << (fd & (8*sizeof(*evts) - 1)); | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,48 @@ | |||||
From e871cc2f15ad121e1e840191f59c6c86d6d0580d Mon Sep 17 00:00:00 2001 | |||||
From: David Carlier <devnexen@gmail.com> | |||||
Date: Mon, 22 Aug 2016 23:27:42 +0100 | |||||
Subject: [PATCH 22/26] MINOR: cfgparse: few memory leaks fixes. | |||||
Some minor memory leak during the config parsing. | |||||
(cherry picked from commit 70d604593d507f50fd99cebecee4b2c47c1d9b73) | |||||
--- | |||||
src/cfgparse.c | 7 ++++++- | |||||
1 file changed, 6 insertions(+), 1 deletion(-) | |||||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||||
index f2a104d..b8289a2 100644 | |||||
--- a/src/cfgparse.c | |||||
+++ b/src/cfgparse.c | |||||
@@ -1597,6 +1597,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm) | |||||
if (logsrv->format < 0) { | |||||
Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]); | |||||
err_code |= ERR_ALERT | ERR_FATAL; | |||||
+ free(logsrv); | |||||
goto out; | |||||
} | |||||
@@ -6777,9 +6778,10 @@ cfg_parse_users(const char *file, int linenum, char **args, int kwm) | |||||
} | |||||
ag->name = strdup(args[1]); | |||||
- if (!ag) { | |||||
+ if (!ag->name) { | |||||
Alert("parsing [%s:%d]: out of memory.\n", file, linenum); | |||||
err_code |= ERR_ALERT | ERR_ABORT; | |||||
+ free(ag); | |||||
goto out; | |||||
} | |||||
@@ -6794,6 +6796,9 @@ cfg_parse_users(const char *file, int linenum, char **args, int kwm) | |||||
Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n", | |||||
file, linenum, args[0]); | |||||
err_code |= ERR_ALERT | ERR_FATAL; | |||||
+ free(ag->groupusers); | |||||
+ free(ag->name); | |||||
+ free(ag); | |||||
goto out; | |||||
} | |||||
} | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,33 @@ | |||||
From 5370c6774a333b2b3989639275d4093fdc541db9 Mon Sep 17 00:00:00 2001 | |||||
From: Bertrand Jacquin <bertrand@jacquin.bzh> | |||||
Date: Thu, 6 Oct 2016 00:32:39 +0100 | |||||
Subject: [PATCH 23/26] MINOR: build: Allow linking to device-atlas library | |||||
file | |||||
DeviceAtlas might be installed in a location where a user might not have | |||||
enough permissions to write json.o and dac.o | |||||
(cherry picked from commit 3a2661d6b4218704c828c8a712c87d651bfe29b5) | |||||
--- | |||||
Makefile | 4 ++++ | |||||
1 file changed, 4 insertions(+) | |||||
diff --git a/Makefile b/Makefile | |||||
index 1d0f2bc..0242cae 100644 | |||||
--- a/Makefile | |||||
+++ b/Makefile | |||||
@@ -615,8 +615,12 @@ endif | |||||
DEVICEATLAS_SRC = | |||||
DEVICEATLAS_INC = $(DEVICEATLAS_SRC) | |||||
DEVICEATLAS_LIB = $(DEVICEATLAS_SRC) | |||||
+ifeq ($(DEVICEATLAS_SRC),) | |||||
+OPTIONS_LDFLAGS += -lda | |||||
+else | |||||
OPTIONS_OBJS += $(DEVICEATLAS_LIB)/json.o | |||||
OPTIONS_OBJS += $(DEVICEATLAS_LIB)/dac.o | |||||
+endif | |||||
OPTIONS_OBJS += src/da.o | |||||
OPTIONS_CFLAGS += -DUSE_DEVICEATLAS $(if $(DEVICEATLAS_INC),-I$(DEVICEATLAS_INC)) | |||||
BUILD_OPTIONS += $(call ignore_implicit,USE_DEVICEATLAS) | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,32 @@ | |||||
From f95dc972e2e9e3c245862e45336ff4f014ad5666 Mon Sep 17 00:00:00 2001 | |||||
From: Jorrit Schippers <jorrit@ncode.nl> | |||||
Date: Sat, 9 Apr 2016 20:30:38 +0200 | |||||
Subject: [PATCH 24/26] DOC: Fix typo in description of `-st` parameter in man | |||||
page | |||||
extra "wait". | |||||
(cherry picked from commit 1458fdbe974562158fc40fd72d745d5fd644c939) | |||||
--- | |||||
doc/haproxy.1 | 6 +++--- | |||||
1 file changed, 3 insertions(+), 3 deletions(-) | |||||
diff --git a/doc/haproxy.1 b/doc/haproxy.1 | |||||
index a836d5d..20c9343 100644 | |||||
--- a/doc/haproxy.1 | |||||
+++ b/doc/haproxy.1 | |||||
@@ -149,9 +149,9 @@ PIDs. Technically speaking, \fBSIGTTOU\fP and \fBSIGUSR1\fP are sent. | |||||
.TP | |||||
\fB\-st <pidlist>\fP | |||||
Send TERMINATE signal to the pids in pidlist after startup. The processes | |||||
-which receive this signal will wait immediately terminate, closing all | |||||
-active sessions. This option must be specified last, followed by any number | |||||
-of PIDs. Technically speaking, \fBSIGTTOU\fP and \fBSIGTERM\fP are sent. | |||||
+which receive this signal will terminate immediately, closing all active | |||||
+sessions. This option must be specified last, followed by any number of | |||||
+PIDs. Technically speaking, \fBSIGTTOU\fP and \fBSIGTERM\fP are sent. | |||||
.SH LOGGING | |||||
Since HAProxy can run inside a chroot, it cannot reliably access /dev/log. | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,39 @@ | |||||
From 6026323cd0c235d6ab7ec039e5d735e7ea2e28bf Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Mon, 31 Oct 2016 17:32:20 +0100 | |||||
Subject: [PATCH 25/26] BUG/MEDIUM: peers: on shutdown, wake up the appctx, not | |||||
the stream | |||||
This part was missed when peers were ported to the new applet | |||||
infrastructure in 1.6, the main stream is woken up instead of the | |||||
appctx. This creates a race condition by which it is possible to | |||||
wake the stream at the wrong moment and miss an event. This bug | |||||
might be at least partially responsible for some of the CLOSE_WAIT | |||||
that were reported on peers session upon reload in version 1.6. | |||||
This fix must be backported to 1.6. | |||||
(cherry picked from commit 78c0c50705a5e9d48607b9377adf030bb9d97b34) | |||||
--- | |||||
src/peers.c | 4 +--- | |||||
1 file changed, 1 insertion(+), 3 deletions(-) | |||||
diff --git a/src/peers.c b/src/peers.c | |||||
index 7e1523f..db1f608 100644 | |||||
--- a/src/peers.c | |||||
+++ b/src/peers.c | |||||
@@ -1637,11 +1637,9 @@ static void peer_session_forceshutdown(struct stream * stream) | |||||
if (ps) | |||||
ps->reconnect = tick_add(now_ms, MS_TO_TICKS(50 + random() % 2000)); | |||||
- /* call release to reinit resync states if needed */ | |||||
- peer_session_release(appctx); | |||||
appctx->st0 = PEER_SESS_ST_END; | |||||
appctx->ctx.peers.ptr = NULL; | |||||
- task_wakeup(stream->task, TASK_WOKEN_MSG); | |||||
+ appctx_wakeup(appctx); | |||||
} | |||||
/* Pre-configures a peers frontend to accept incoming connections */ | |||||
-- | |||||
2.7.3 | |||||
@ -0,0 +1,64 @@ | |||||
From ab45181e36b6c4f7d31c5284035937c2d0be37eb Mon Sep 17 00:00:00 2001 | |||||
From: Willy Tarreau <w@1wt.eu> | |||||
Date: Mon, 31 Oct 2016 17:46:57 +0100 | |||||
Subject: [PATCH 26/26] BUG/MEDIUM: peers: fix use after free in | |||||
peer_session_create() | |||||
In case of resource allocation error, peer_session_create() frees | |||||
everything allocated and returns a pointer to the stream/session that | |||||
was put back into the free pool. This stream/session is then assigned | |||||
to ps->{stream,session} with no error control. This means that it is | |||||
perfectly possible to have a new stream or session being both used for | |||||
a regular communication and for a peer at the same time. | |||||
In fact it is the only way (for now) to explain a CLOSE_WAIT on peers | |||||
connections that was caught in this dump with the stream interface in | |||||
SI_ST_CON state while the error field proves the state ought to have | |||||
been SI_ST_DIS, very likely indicating two concurrent accesses on the | |||||
same area : | |||||
0x7dbd50: [31/Oct/2016:17:53:41.267510] id=0 proto=tcpv4 | |||||
flags=0x23006, conn_retries=0, srv_conn=(nil), pend_pos=(nil) | |||||
frontend=myhost2 (id=4294967295 mode=tcp), listener=? (id=0) | |||||
backend=<NONE> (id=-1 mode=-) addr=127.0.0.1:41432 | |||||
server=<NONE> (id=-1) addr=127.0.0.1:8521 | |||||
task=0x7dbcd8 (state=0x08 nice=0 calls=2 exp=<NEVER> age=1m5s) | |||||
si[0]=0x7dbf48 (state=CLO flags=0x4040 endp0=APPCTX:0x7d99c8 exp=<NEVER>, et=0x000) | |||||
si[1]=0x7dbf68 (state=CON flags=0x50 endp1=CONN:0x7dc0b8 exp=<NEVER>, et=0x020) | |||||
app0=0x7d99c8 st0=11 st1=0 st2=0 applet=<PEER> | |||||
co1=0x7dc0b8 ctrl=tcpv4 xprt=RAW data=STRM target=PROXY:0x7fe62028a010 | |||||
flags=0x0020b310 fd=7 fd.state=22 fd.cache=0 updt=0 | |||||
req=0x7dbd60 (f=0x80a020 an=0x0 pipe=0 tofwd=0 total=0) | |||||
an_exp=<NEVER> rex=<NEVER> wex=<NEVER> | |||||
buf=0x78a3c0 data=0x78a3d4 o=0 p=0 req.next=0 i=0 size=0 | |||||
res=0x7dbda0 (f=0x80402020 an=0x0 pipe=0 tofwd=0 total=0) | |||||
an_exp=<NEVER> rex=<NEVER> wex=<NEVER> | |||||
buf=0x78a3c0 data=0x78a3d4 o=0 p=0 rsp.next=0 i=0 size=0 | |||||
Special thanks to Arnaud Gavara who provided lots of valuable input and | |||||
ran some validation testing on this patch. | |||||
This fix must be backported to 1.6 and 1.5. Note that in 1.5 the | |||||
session is not assigned from within the function so some extra checks | |||||
may be needed in the callers. | |||||
(cherry picked from commit b21d08e2492bfbf9d2341ce9f148cb9845927862) | |||||
--- | |||||
src/peers.c | 2 +- | |||||
1 file changed, 1 insertion(+), 1 deletion(-) | |||||
diff --git a/src/peers.c b/src/peers.c | |||||
index db1f608..c8be59a 100644 | |||||
--- a/src/peers.c | |||||
+++ b/src/peers.c | |||||
@@ -1747,7 +1747,7 @@ static struct stream *peer_session_create(struct peers *peers, struct peer *peer | |||||
out_free_appctx: | |||||
appctx_free(appctx); | |||||
out_close: | |||||
- return s; | |||||
+ return NULL; | |||||
} | |||||
/* | |||||
-- | |||||
2.7.3 | |||||