- bump to version 1.5.5 Signed-off-by: Thomas Heil <heil@terminal-consulting.de>lilik-openwrt-22.03
@ -1,35 +0,0 @@ | |||
From e99d44d4bc3423b721c7f654fd1778b9822a94e3 Mon Sep 17 00:00:00 2001 | |||
From: Olivier <webmaster@ajeux.com> | |||
Date: Fri, 5 Sep 2014 18:49:10 +0200 | |||
Subject: [PATCH 01/13] DOC: clearly state that the "show sess" output format | |||
is not fixed | |||
It requires to look at the code (src/dumpstats.c) since the format may | |||
change at any moment. | |||
(cherry picked from commit ce31e6e3baebe75a2e6f6b5c66553db8d76dff0c) | |||
--- | |||
doc/configuration.txt | 8 +++++--- | |||
1 file changed, 5 insertions(+), 3 deletions(-) | |||
diff --git a/doc/configuration.txt b/doc/configuration.txt | |||
index 19df5ae..1ecf15a 100644 | |||
--- a/doc/configuration.txt | |||
+++ b/doc/configuration.txt | |||
@@ -13734,9 +13734,11 @@ show sess <id> | |||
of "show sess" (it corresponds to the session pointer). Those information are | |||
useless to most users but may be used by haproxy developers to troubleshoot a | |||
complex bug. The output format is intentionally not documented so that it can | |||
- freely evolve depending on demands. The special id "all" dumps the states of | |||
- all sessions, which can be avoided as much as possible as it is highly CPU | |||
- intensive and can take a lot of time. | |||
+ freely evolve depending on demands. You may find a description of all fields | |||
+ returned in src/dumpstats.c | |||
+ | |||
+ The special id "all" dumps the states of all sessions, which must be avoided | |||
+ as much as possible as it is highly CPU intensive and can take a lot of time. | |||
show stat [<iid> <type> <sid>] | |||
Dump statistics in the CSV format. By passing <id>, <type> and <sid>, it is | |||
-- | |||
1.8.5.5 | |||
@ -1,28 +0,0 @@ | |||
From 815d7d5c348575181874429b93b0ebdb0cf873c2 Mon Sep 17 00:00:00 2001 | |||
From: Olivier Doucet <webmaster@ajeux.com> | |||
Date: Mon, 8 Sep 2014 11:23:00 +0200 | |||
Subject: [PATCH 02/13] MINOR: stats: fix minor typo fix in | |||
stats_dump_errors_to_buffer() | |||
Remove the space before the colon to match the format used in the frontend. | |||
(cherry picked from commit 08afdcb47bc39c071787f8fc2066776e1c5e8607) | |||
--- | |||
src/dumpstats.c | 2 +- | |||
1 file changed, 1 insertion(+), 1 deletion(-) | |||
diff --git a/src/dumpstats.c b/src/dumpstats.c | |||
index 5365042..09bc7f6 100644 | |||
--- a/src/dumpstats.c | |||
+++ b/src/dumpstats.c | |||
@@ -6045,7 +6045,7 @@ static int stats_dump_errors_to_buffer(struct stream_interface *si) | |||
break; | |||
case 1: | |||
chunk_appendf(&trash, | |||
- " backend %s (#%d) : invalid response\n" | |||
+ " backend %s (#%d): invalid response\n" | |||
" frontend %s (#%d)", | |||
appctx->ctx.errors.px->id, appctx->ctx.errors.px->uuid, | |||
es->oe->id, es->oe->uuid); | |||
-- | |||
1.8.5.5 | |||
@ -1,105 +0,0 @@ | |||
From 62c8565cd5bbda6ac0dd818fa26922eeaef1605c Mon Sep 17 00:00:00 2001 | |||
From: Conrad Hoffmann <conrad@soundcloud.com> | |||
Date: Mon, 28 Jul 2014 23:52:20 +0200 | |||
Subject: [PATCH 03/13] MEDIUM: Improve signal handling in systemd wrapper. | |||
Move all code out of the signal handlers, since this is potentially | |||
dangerous. To make sure the signal handlers behave as expected, use | |||
sigaction() instead of signal(). That also obsoletes messing with | |||
the signal mask after restart. | |||
Signed-off-by: Conrad Hoffmann <conrad@soundcloud.com> | |||
(cherry picked from commit 5b5ea9c93384da49eea0f67ebed0966d4167b17a) | |||
--- | |||
src/haproxy-systemd-wrapper.c | 37 ++++++++++++++++++++++++------------- | |||
1 file changed, 24 insertions(+), 13 deletions(-) | |||
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c | |||
index 529b213..90a94ce 100644 | |||
--- a/src/haproxy-systemd-wrapper.c | |||
+++ b/src/haproxy-systemd-wrapper.c | |||
@@ -22,6 +22,8 @@ | |||
#define SD_DEBUG "<7>" | |||
#define SD_NOTICE "<5>" | |||
+static volatile sig_atomic_t caught_signal; | |||
+ | |||
static char *pid_file = "/run/haproxy.pid"; | |||
static int wrapper_argc; | |||
static char **wrapper_argv; | |||
@@ -103,7 +105,12 @@ static int read_pids(char ***pid_strv) | |||
return read; | |||
} | |||
-static void sigusr2_handler(int signum __attribute__((unused))) | |||
+static void signal_handler(int signum) | |||
+{ | |||
+ caught_signal = signum; | |||
+} | |||
+ | |||
+static void do_restart(void) | |||
{ | |||
setenv(REEXEC_FLAG, "1", 1); | |||
fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: re-executing\n"); | |||
@@ -111,7 +118,7 @@ static void sigusr2_handler(int signum __attribute__((unused))) | |||
execv(wrapper_argv[0], wrapper_argv); | |||
} | |||
-static void sigint_handler(int signum __attribute__((unused))) | |||
+static void do_shutdown(void) | |||
{ | |||
int i, pid; | |||
char **pid_strv = NULL; | |||
@@ -147,25 +154,21 @@ int main(int argc, char **argv) | |||
--argc; ++argv; | |||
init(argc, argv); | |||
- signal(SIGINT, &sigint_handler); | |||
- signal(SIGUSR2, &sigusr2_handler); | |||
+ struct sigaction sa; | |||
+ memset(&sa, 0, sizeof(struct sigaction)); | |||
+ sa.sa_handler = &signal_handler; | |||
+ sigaction(SIGUSR2, &sa, NULL); | |||
+ sigaction(SIGINT, &sa, NULL); | |||
if (getenv(REEXEC_FLAG) != NULL) { | |||
/* We are being re-executed: restart HAProxy gracefully */ | |||
int i; | |||
char **pid_strv = NULL; | |||
int nb_pid = read_pids(&pid_strv); | |||
- sigset_t sigs; | |||
unsetenv(REEXEC_FLAG); | |||
spawn_haproxy(pid_strv, nb_pid); | |||
- /* Unblock SIGUSR2 which was blocked by the signal handler | |||
- * before re-exec */ | |||
- sigprocmask(SIG_BLOCK, NULL, &sigs); | |||
- sigdelset(&sigs, SIGUSR2); | |||
- sigprocmask(SIG_SETMASK, &sigs, NULL); | |||
- | |||
for (i = 0; i < nb_pid; ++i) | |||
free(pid_strv[i]); | |||
free(pid_strv); | |||
@@ -176,8 +179,16 @@ int main(int argc, char **argv) | |||
} | |||
status = -1; | |||
- while (-1 != wait(&status) || errno == EINTR) | |||
- ; | |||
+ while (-1 != wait(&status) || errno == EINTR) { | |||
+ if (caught_signal == SIGUSR2) { | |||
+ caught_signal = 0; | |||
+ do_restart(); | |||
+ } | |||
+ else if (caught_signal == SIGINT) { | |||
+ caught_signal = 0; | |||
+ do_shutdown(); | |||
+ } | |||
+ } | |||
fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: exit, haproxy RC=%d\n", | |||
status); | |||
-- | |||
1.8.5.5 | |||
@ -1,48 +0,0 @@ | |||
From 6bb7bf7949dd019403b65f400c4b3d0d8589327b Mon Sep 17 00:00:00 2001 | |||
From: Matt Robenolt <matt@ydekproductions.com> | |||
Date: Thu, 11 Sep 2014 05:19:30 +0000 | |||
Subject: [PATCH 04/13] MINOR: Also accept SIGHUP/SIGTERM in systemd-wrapper | |||
My proposal is to let haproxy-systemd-wrapper also accept normal | |||
SIGHUP/SIGTERM signals to play nicely with other process managers | |||
besides just systemd. In my use case, this will be for using with | |||
runit which has to ability to change the signal used for a | |||
"reload" or "stop" command. It also might be worth renaming this | |||
bin to just haproxy-wrapper or something of that sort to separate | |||
itself away from systemd. But that's a different discussion. :) | |||
(cherry picked from commit c54bdd2a118161b4dc36963b4201edfa7341dadb) | |||
--- | |||
src/haproxy-systemd-wrapper.c | 6 ++++-- | |||
1 file changed, 4 insertions(+), 2 deletions(-) | |||
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c | |||
index 90a94ce..cc8baa8 100644 | |||
--- a/src/haproxy-systemd-wrapper.c | |||
+++ b/src/haproxy-systemd-wrapper.c | |||
@@ -158,7 +158,9 @@ int main(int argc, char **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 */ | |||
@@ -180,11 +182,11 @@ int main(int argc, char **argv) | |||
status = -1; | |||
while (-1 != wait(&status) || errno == EINTR) { | |||
- if (caught_signal == SIGUSR2) { | |||
+ if (caught_signal == SIGUSR2 || caught_signal == SIGHUP) { | |||
caught_signal = 0; | |||
do_restart(); | |||
} | |||
- else if (caught_signal == SIGINT) { | |||
+ else if (caught_signal == SIGINT || caught_signal == SIGTERM) { | |||
caught_signal = 0; | |||
do_shutdown(); | |||
} | |||
-- | |||
1.8.5.5 | |||
@ -1,52 +0,0 @@ | |||
From 531485c08ffb15b939a28ecf47090e4c93341d1b Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Tue, 16 Sep 2014 15:48:15 +0200 | |||
Subject: [PATCH 05/13] DOC: indicate in the doc that track-sc* can wait if | |||
data are missing | |||
Since commit 1b71eb5 ("BUG/MEDIUM: counters: fix track-sc* to wait on | |||
unstable contents"), we don't need the "if HTTP" anymore. But the doc | |||
was not updated to reflect this. | |||
Since this change was backported to 1.5, this doc update should be | |||
backported as well. | |||
(cherry picked from commit 4d54c7ca0286588de5060acce9aff8aa9645bb98) | |||
--- | |||
doc/configuration.txt | 10 +++++----- | |||
1 file changed, 5 insertions(+), 5 deletions(-) | |||
diff --git a/doc/configuration.txt b/doc/configuration.txt | |||
index 1ecf15a..3c75c92 100644 | |||
--- a/doc/configuration.txt | |||
+++ b/doc/configuration.txt | |||
@@ -7470,9 +7470,9 @@ tcp-request content <action> [{if | unless} <condition>] | |||
contents will always be immediately present when the rule is evaluated first. | |||
Tracking layer7 information is also possible provided that the information | |||
- are present when the rule is processed. The current solution for making the | |||
- rule engine wait for such information is to set an inspect delay and to | |||
- condition its execution with an ACL relying on such information. | |||
+ are present when the rule is processed. The rule processing engine is able to | |||
+ wait until the inspect delay expires when the data to be tracked is not yet | |||
+ available. | |||
Example: | |||
# Accept HTTP requests containing a Host header saying "example.com" | |||
@@ -7497,12 +7497,12 @@ tcp-request content <action> [{if | unless} <condition>] | |||
Example: | |||
# Track the last IP from X-Forwarded-For | |||
tcp-request inspect-delay 10s | |||
- tcp-request content track-sc0 hdr(x-forwarded-for,-1) if HTTP | |||
+ tcp-request content track-sc0 hdr(x-forwarded-for,-1) | |||
Example: | |||
# track request counts per "base" (concatenation of Host+URL) | |||
tcp-request inspect-delay 10s | |||
- tcp-request content track-sc0 base table req-rate if HTTP | |||
+ tcp-request content track-sc0 base table req-rate | |||
Example: track per-frontend and per-backend counters, block abusers at the | |||
frontend when the backend detects abuse. | |||
-- | |||
1.8.5.5 | |||
@ -1,80 +0,0 @@ | |||
From 0cb4b899d370b9d04b3457a1d75dbd658c1a1646 Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Tue, 16 Sep 2014 10:40:38 +0200 | |||
Subject: [PATCH 06/13] MEDIUM: http: enable header manipulation for 101 | |||
responses | |||
Ryan Brock reported that server stickiness did not work for WebSocket | |||
because the cookies and headers are not modified on 1xx responses. He | |||
found that his browser correctly presents the cookies learned on 101 | |||
responses, which was not specifically defined in the WebSocket spec, | |||
nor in the cookie spec. 101 is a very special case. Being part of 1xx, | |||
it's an interim response. But within 1xx, it's special because it's | |||
the last HTTP/1 response that transits on the wire, which is different | |||
from 100 or 102 which may appear multiple times. So in that sense, we | |||
can consider it as a final response regarding HTTP/1, and it makes | |||
sense to allow header processing there. Note that we still ensure not | |||
to mangle the Connection header, which is critical for HTTP upgrade to | |||
continue to work smoothly with agents that are a bit picky about what | |||
tokens are found there. | |||
The rspadd rules are now processed for 101 responses as well, but the | |||
cache-control checks are not performed (since no body is delivered). | |||
Ryan confirmed that this patch works for him. | |||
It would make sense to backport it to 1.5 given that it improves end | |||
user experience on WebSocket servers. | |||
(cherry picked from commit ce730de86719d0b5079dd8b0843559e4ff0a1ecc) | |||
--- | |||
src/proto_http.c | 12 +++++++----- | |||
1 file changed, 7 insertions(+), 5 deletions(-) | |||
diff --git a/src/proto_http.c b/src/proto_http.c | |||
index 4d27b2c..7e35c8b 100644 | |||
--- a/src/proto_http.c | |||
+++ b/src/proto_http.c | |||
@@ -6249,7 +6249,7 @@ int http_process_res_common(struct session *s, struct channel *rep, int an_bit, | |||
/* add response headers from the rule sets in the same order */ | |||
list_for_each_entry(wl, &rule_set->rsp_add, list) { | |||
- if (txn->status < 200) | |||
+ if (txn->status < 200 && txn->status != 101) | |||
break; | |||
if (wl->cond) { | |||
int ret = acl_exec_cond(wl->cond, px, s, txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL); | |||
@@ -6270,7 +6270,7 @@ int http_process_res_common(struct session *s, struct channel *rep, int an_bit, | |||
} | |||
/* OK that's all we can do for 1xx responses */ | |||
- if (unlikely(txn->status < 200)) | |||
+ if (unlikely(txn->status < 200 && txn->status != 101)) | |||
goto skip_header_mangling; | |||
/* | |||
@@ -6283,7 +6283,7 @@ int http_process_res_common(struct session *s, struct channel *rep, int an_bit, | |||
/* | |||
* Check for cache-control or pragma headers if required. | |||
*/ | |||
- if ((s->be->options & PR_O_CHK_CACHE) || (s->be->ck_opts & PR_CK_NOC)) | |||
+ if (((s->be->options & PR_O_CHK_CACHE) || (s->be->ck_opts & PR_CK_NOC)) && txn->status != 101) | |||
check_response_for_cacheability(s, rep); | |||
/* | |||
@@ -6399,9 +6399,11 @@ int http_process_res_common(struct session *s, struct channel *rep, int an_bit, | |||
* Adjust "Connection: close" or "Connection: keep-alive" if needed. | |||
* If an "Upgrade" token is found, the header is left untouched in order | |||
* not to have to deal with some client bugs : some of them fail an upgrade | |||
- * if anything but "Upgrade" is present in the Connection header. | |||
+ * if anything but "Upgrade" is present in the Connection header. We don't | |||
+ * want to touch any 101 response either since it's switching to another | |||
+ * protocol. | |||
*/ | |||
- if (!(txn->flags & TX_HDR_CONN_UPG) && | |||
+ if ((txn->status != 101) && !(txn->flags & TX_HDR_CONN_UPG) && | |||
(((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) || | |||
((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL || | |||
(s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL))) { | |||
-- | |||
1.8.5.5 | |||
@ -1,60 +0,0 @@ | |||
From b53934eec71ab34eb3762a89cec326360a5b0bc5 Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Tue, 16 Sep 2014 11:31:31 +0200 | |||
Subject: [PATCH 07/13] BUG/MEDIUM: config: propagate frontend to backend | |||
process binding again. | |||
This basically reverts 3507d5d ("MEDIUM: proxy: only adjust the backend's | |||
bind-process when already set"). It was needed during the transition to | |||
the new process binding method but is causing trouble now because frontend | |||
to backend binding is not properly propagated. | |||
This fix should be backported to 1.5. | |||
(cherry picked from commit 8a3478ed31a16904f45178c153f4649faf6de675) | |||
--- | |||
src/cfgparse.c | 15 ++++++--------- | |||
1 file changed, 6 insertions(+), 9 deletions(-) | |||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||
index 943eba0..5288600 100644 | |||
--- a/src/cfgparse.c | |||
+++ b/src/cfgparse.c | |||
@@ -6165,9 +6165,8 @@ int check_config_validity() | |||
/* we force the backend to be present on at least all of | |||
* the frontend's processes. | |||
*/ | |||
- if (target->bind_proc) | |||
- target->bind_proc = curproxy->bind_proc ? | |||
- (target->bind_proc | curproxy->bind_proc) : 0; | |||
+ target->bind_proc = curproxy->bind_proc ? | |||
+ (target->bind_proc | curproxy->bind_proc) : 0; | |||
/* Emit a warning if this proxy also has some servers */ | |||
if (curproxy->srv) { | |||
@@ -6203,9 +6202,8 @@ int check_config_validity() | |||
/* we force the backend to be present on at least all of | |||
* the frontend's processes. | |||
*/ | |||
- if (target->bind_proc) | |||
- target->bind_proc = curproxy->bind_proc ? | |||
- (target->bind_proc | curproxy->bind_proc) : 0; | |||
+ target->bind_proc = curproxy->bind_proc ? | |||
+ (target->bind_proc | curproxy->bind_proc) : 0; | |||
} | |||
} | |||
} | |||
@@ -6257,9 +6255,8 @@ int check_config_validity() | |||
/* we force the backend to be present on at least all of | |||
* the frontend's processes. | |||
*/ | |||
- if (target->bind_proc) | |||
- target->bind_proc = curproxy->bind_proc ? | |||
- (target->bind_proc | curproxy->bind_proc) : 0; | |||
+ target->bind_proc = curproxy->bind_proc ? | |||
+ (target->bind_proc | curproxy->bind_proc) : 0; | |||
} | |||
} | |||
-- | |||
1.8.5.5 | |||
@ -1,142 +0,0 @@ | |||
From 5436afc9488531a5e2adff3a1a766af375e0922c Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Tue, 16 Sep 2014 12:17:36 +0200 | |||
Subject: [PATCH 08/13] MEDIUM: config: properly propagate process binding | |||
between proxies | |||
We now recursively propagate the bind-process values between frontends | |||
and backends instead of doing it during name resolving. This ensures | |||
that we're able to properly propagate all the bind-process directives | |||
even across "listen" instances, which are not perfectly covered at the | |||
moment, depending on the declaration order. | |||
(cherry picked from commit 64ab6077b768ee02b04a36b30ee195639a2fabc1) | |||
--- | |||
src/cfgparse.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++------------ | |||
1 file changed, 65 insertions(+), 16 deletions(-) | |||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||
index 5288600..b9853ef 100644 | |||
--- a/src/cfgparse.c | |||
+++ b/src/cfgparse.c | |||
@@ -5932,6 +5932,64 @@ int readcfgfile(const char *file) | |||
return err_code; | |||
} | |||
+/* This function propagates processes from frontend <from> to backend <to> so | |||
+ * that it is always guaranteed that a backend pointed to by a frontend is | |||
+ * bound to all of its processes. After that, if the target is a "listen" | |||
+ * instance, the function recursively descends the target's own targets along | |||
+ * default_backend, use_backend rules, and reqsetbe rules. Since the bits are | |||
+ * checked first to ensure that <to> is already bound to all processes of | |||
+ * <from>, there is no risk of looping and we ensure to follow the shortest | |||
+ * path to the destination. | |||
+ * | |||
+ * It is possible to set <to> to NULL for the first call so that the function | |||
+ * takes care of visiting the initial frontend in <from>. | |||
+ * | |||
+ * It is important to note that the function relies on the fact that all names | |||
+ * have already been resolved. | |||
+ */ | |||
+void propagate_processes(struct proxy *from, struct proxy *to) | |||
+{ | |||
+ struct switching_rule *rule; | |||
+ struct hdr_exp *exp; | |||
+ | |||
+ if (to) { | |||
+ /* check whether we need to go down */ | |||
+ if (from->bind_proc && | |||
+ (from->bind_proc & to->bind_proc) == from->bind_proc) | |||
+ return; | |||
+ | |||
+ if (!from->bind_proc && !to->bind_proc) | |||
+ return; | |||
+ | |||
+ to->bind_proc = from->bind_proc ? | |||
+ (to->bind_proc | from->bind_proc) : 0; | |||
+ | |||
+ /* now propagate down */ | |||
+ from = to; | |||
+ } | |||
+ | |||
+ if (!from->cap & PR_CAP_FE) | |||
+ return; | |||
+ | |||
+ /* default_backend */ | |||
+ if (from->defbe.be) | |||
+ propagate_processes(from, from->defbe.be); | |||
+ | |||
+ /* use_backend */ | |||
+ list_for_each_entry(rule, &from->switching_rules, list) { | |||
+ to = rule->be.backend; | |||
+ propagate_processes(from, to); | |||
+ } | |||
+ | |||
+ /* reqsetbe */ | |||
+ for (exp = from->req_exp; exp != NULL; exp = exp->next) { | |||
+ if (exp->action != ACT_SETBE) | |||
+ continue; | |||
+ to = (struct proxy *)exp->replace; | |||
+ propagate_processes(from, to); | |||
+ } | |||
+} | |||
+ | |||
/* | |||
* Returns the error code, 0 if OK, or any combination of : | |||
* - ERR_ABORT: must abort ASAP | |||
@@ -6162,11 +6220,6 @@ int check_config_validity() | |||
} else { | |||
free(curproxy->defbe.name); | |||
curproxy->defbe.be = target; | |||
- /* we force the backend to be present on at least all of | |||
- * the frontend's processes. | |||
- */ | |||
- target->bind_proc = curproxy->bind_proc ? | |||
- (target->bind_proc | curproxy->bind_proc) : 0; | |||
/* Emit a warning if this proxy also has some servers */ | |||
if (curproxy->srv) { | |||
@@ -6199,11 +6252,6 @@ int check_config_validity() | |||
} else { | |||
free((void *)exp->replace); | |||
exp->replace = (const char *)target; | |||
- /* we force the backend to be present on at least all of | |||
- * the frontend's processes. | |||
- */ | |||
- target->bind_proc = curproxy->bind_proc ? | |||
- (target->bind_proc | curproxy->bind_proc) : 0; | |||
} | |||
} | |||
} | |||
@@ -6252,15 +6300,10 @@ int check_config_validity() | |||
} else { | |||
free((void *)rule->be.name); | |||
rule->be.backend = target; | |||
- /* we force the backend to be present on at least all of | |||
- * the frontend's processes. | |||
- */ | |||
- target->bind_proc = curproxy->bind_proc ? | |||
- (target->bind_proc | curproxy->bind_proc) : 0; | |||
} | |||
} | |||
- /* find the target proxy for 'use_backend' rules */ | |||
+ /* find the target server for 'use_server' rules */ | |||
list_for_each_entry(srule, &curproxy->server_rules, list) { | |||
struct server *target = findserver(curproxy, srule->srv.name); | |||
@@ -7131,6 +7174,12 @@ out_uri_auth_compat: | |||
} | |||
} | |||
+ /* At this point, target names have already been resolved */ | |||
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
+ if (curproxy->cap & PR_CAP_FE) | |||
+ propagate_processes(curproxy, NULL); | |||
+ } | |||
+ | |||
/* automatically compute fullconn if not set. We must not do it in the | |||
* loop above because cross-references are not yet fully resolved. | |||
*/ | |||
-- | |||
1.8.5.5 | |||
@ -1,93 +0,0 @@ | |||
From e56c4f1f76c6731a5a0f4b128540071cffeb1951 Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Tue, 16 Sep 2014 13:21:03 +0200 | |||
Subject: [PATCH 09/13] MEDIUM: config: make the frontends automatically bind | |||
to the listeners' processes | |||
When a frontend does not have any bind-process directive, make it | |||
automatically bind to the union of all of its listeners' processes | |||
instead of binding to all processes. That will make it possible to | |||
have the expected behaviour without having to explicitly specify a | |||
bind-process directive. | |||
Note that if the listeners are not bound to a specific process, the | |||
default is still to bind to all processes. | |||
This change could be backported to 1.5 as it simplifies process | |||
management, and was planned to be done during the 1.5 development phase. | |||
(cherry picked from commit b369a045d545b41ef2b250bf747caf83c97e0ca8) | |||
--- | |||
doc/configuration.txt | 4 ++++ | |||
src/cfgparse.c | 36 ++++++++++++++++++++++++++++++++++++ | |||
2 files changed, 40 insertions(+) | |||
diff --git a/doc/configuration.txt b/doc/configuration.txt | |||
index 3c75c92..1e32057 100644 | |||
--- a/doc/configuration.txt | |||
+++ b/doc/configuration.txt | |||
@@ -1905,6 +1905,10 @@ bind-process [ all | odd | even | <number 1-64>[-<number 1-64>] ] ... | |||
Each "bind" line may further be limited to a subset of the proxy's processes, | |||
please consult the "process" bind keyword in section 5.1. | |||
+ When a frontend has no explicit "bind-process" line, it tries to bind to all | |||
+ the processes referenced by its "bind" lines. That means that frontends can | |||
+ easily adapt to their listeners' processes. | |||
+ | |||
If some backends are referenced by frontends bound to other processes, the | |||
backend automatically inherits the frontend's processes. | |||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||
index b9853ef..d53f69e 100644 | |||
--- a/src/cfgparse.c | |||
+++ b/src/cfgparse.c | |||
@@ -7175,11 +7175,47 @@ out_uri_auth_compat: | |||
} | |||
/* At this point, target names have already been resolved */ | |||
+ | |||
+ /* Make each frontend inherit bind-process from its listeners when not specified. */ | |||
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
+ if (curproxy->bind_proc) | |||
+ continue; | |||
+ | |||
+ list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) { | |||
+ unsigned long mask; | |||
+ | |||
+ mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL; | |||
+ curproxy->bind_proc |= mask; | |||
+ } | |||
+ | |||
+ if (!curproxy->bind_proc) | |||
+ curproxy->bind_proc = ~0UL; | |||
+ } | |||
+ | |||
+ if (global.stats_fe) { | |||
+ list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) { | |||
+ unsigned long mask; | |||
+ | |||
+ mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL; | |||
+ global.stats_fe->bind_proc |= mask; | |||
+ } | |||
+ if (!global.stats_fe->bind_proc) | |||
+ global.stats_fe->bind_proc = ~0UL; | |||
+ } | |||
+ | |||
+ /* propagate bindings from frontends to backends */ | |||
for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
if (curproxy->cap & PR_CAP_FE) | |||
propagate_processes(curproxy, NULL); | |||
} | |||
+ /* Bind each unbound backend to all processes when not specified. */ | |||
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
+ if (curproxy->bind_proc) | |||
+ continue; | |||
+ curproxy->bind_proc = ~0UL; | |||
+ } | |||
+ | |||
/* automatically compute fullconn if not set. We must not do it in the | |||
* loop above because cross-references are not yet fully resolved. | |||
*/ | |||
-- | |||
1.8.5.5 | |||
@ -1,209 +0,0 @@ | |||
From 91b00c2194b728ccd61133cca83f03de3650b674 Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Tue, 16 Sep 2014 13:41:21 +0200 | |||
Subject: [PATCH 10/13] MEDIUM: config: compute the exact bind-process before | |||
listener's maxaccept | |||
This is a continuation of previous patch, the listener's maxaccept is divided | |||
by the number of processes, so it's best if we can swap the two blocks so that | |||
the number of processes is already known when computing the maxaccept value. | |||
(cherry picked from commit 419ead8eca9237f9cc2ec32630d96fde333282ee) | |||
--- | |||
src/cfgparse.c | 156 ++++++++++++++++++++++++++++++--------------------------- | |||
1 file changed, 81 insertions(+), 75 deletions(-) | |||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||
index d53f69e..f3907bf 100644 | |||
--- a/src/cfgparse.c | |||
+++ b/src/cfgparse.c | |||
@@ -6042,12 +6042,11 @@ int check_config_validity() | |||
proxy = next; | |||
} | |||
- while (curproxy != NULL) { | |||
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
struct switching_rule *rule; | |||
struct server_rule *srule; | |||
struct sticking_rule *mrule; | |||
struct tcp_rule *trule; | |||
- struct listener *listener; | |||
unsigned int next_id; | |||
int nbproc; | |||
@@ -6115,14 +6114,6 @@ int check_config_validity() | |||
} | |||
} | |||
- /* here, if bind_proc is null, it means no limit, otherwise it's explicit. | |||
- * We now check how many processes the proxy will effectively run on. | |||
- */ | |||
- | |||
- nbproc = global.nbproc; | |||
- if (curproxy->bind_proc) | |||
- nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc)); | |||
- | |||
if (global.nbproc > 1 && curproxy->table.peers.name) { | |||
Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n", | |||
curproxy->id); | |||
@@ -7005,6 +6996,86 @@ out_uri_auth_compat: | |||
if (curproxy->options2 & PR_O2_RDPC_PRST) | |||
curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE; | |||
} | |||
+ } | |||
+ | |||
+ /***********************************************************/ | |||
+ /* At this point, target names have already been resolved. */ | |||
+ /***********************************************************/ | |||
+ | |||
+ /* Check multi-process mode compatibility */ | |||
+ | |||
+ if (global.nbproc > 1 && global.stats_fe) { | |||
+ list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) { | |||
+ unsigned long mask; | |||
+ | |||
+ mask = nbits(global.nbproc); | |||
+ if (global.stats_fe->bind_proc) | |||
+ mask &= global.stats_fe->bind_proc; | |||
+ | |||
+ if (bind_conf->bind_proc) | |||
+ mask &= bind_conf->bind_proc; | |||
+ | |||
+ /* stop here if more than one process is used */ | |||
+ if (popcount(mask) > 1) | |||
+ break; | |||
+ } | |||
+ if (&bind_conf->by_fe != &global.stats_fe->conf.bind) { | |||
+ Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding globally using 'stats bind-process' or per socket using the 'process' attribute.\n"); | |||
+ } | |||
+ } | |||
+ | |||
+ /* Make each frontend inherit bind-process from its listeners when not specified. */ | |||
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
+ if (curproxy->bind_proc) | |||
+ continue; | |||
+ | |||
+ list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) { | |||
+ unsigned long mask; | |||
+ | |||
+ mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL; | |||
+ curproxy->bind_proc |= mask; | |||
+ } | |||
+ | |||
+ if (!curproxy->bind_proc) | |||
+ curproxy->bind_proc = ~0UL; | |||
+ } | |||
+ | |||
+ if (global.stats_fe) { | |||
+ list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) { | |||
+ unsigned long mask; | |||
+ | |||
+ mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL; | |||
+ global.stats_fe->bind_proc |= mask; | |||
+ } | |||
+ if (!global.stats_fe->bind_proc) | |||
+ global.stats_fe->bind_proc = ~0UL; | |||
+ } | |||
+ | |||
+ /* propagate bindings from frontends to backends */ | |||
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
+ if (curproxy->cap & PR_CAP_FE) | |||
+ propagate_processes(curproxy, NULL); | |||
+ } | |||
+ | |||
+ /* Bind each unbound backend to all processes when not specified. */ | |||
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
+ if (curproxy->bind_proc) | |||
+ continue; | |||
+ curproxy->bind_proc = ~0UL; | |||
+ } | |||
+ | |||
+ /*******************************************************/ | |||
+ /* At this step, all proxies have a non-null bind_proc */ | |||
+ /*******************************************************/ | |||
+ | |||
+ /* perform the final checks before creating tasks */ | |||
+ | |||
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
+ struct listener *listener; | |||
+ unsigned int next_id; | |||
+ int nbproc; | |||
+ | |||
+ nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc)); | |||
#ifdef USE_OPENSSL | |||
/* Configure SSL for each bind line. | |||
@@ -7149,71 +7220,6 @@ out_uri_auth_compat: | |||
curproxy->id); | |||
cfgerr++; | |||
} | |||
- | |||
- curproxy = curproxy->next; | |||
- } | |||
- | |||
- /* Check multi-process mode compatibility */ | |||
- if (global.nbproc > 1 && global.stats_fe) { | |||
- list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) { | |||
- unsigned long mask; | |||
- | |||
- mask = nbits(global.nbproc); | |||
- if (global.stats_fe->bind_proc) | |||
- mask &= global.stats_fe->bind_proc; | |||
- | |||
- if (bind_conf->bind_proc) | |||
- mask &= bind_conf->bind_proc; | |||
- | |||
- /* stop here if more than one process is used */ | |||
- if (popcount(mask) > 1) | |||
- break; | |||
- } | |||
- if (&bind_conf->by_fe != &global.stats_fe->conf.bind) { | |||
- Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding globally using 'stats bind-process' or per socket using the 'process' attribute.\n"); | |||
- } | |||
- } | |||
- | |||
- /* At this point, target names have already been resolved */ | |||
- | |||
- /* Make each frontend inherit bind-process from its listeners when not specified. */ | |||
- for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
- if (curproxy->bind_proc) | |||
- continue; | |||
- | |||
- list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) { | |||
- unsigned long mask; | |||
- | |||
- mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL; | |||
- curproxy->bind_proc |= mask; | |||
- } | |||
- | |||
- if (!curproxy->bind_proc) | |||
- curproxy->bind_proc = ~0UL; | |||
- } | |||
- | |||
- if (global.stats_fe) { | |||
- list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) { | |||
- unsigned long mask; | |||
- | |||
- mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL; | |||
- global.stats_fe->bind_proc |= mask; | |||
- } | |||
- if (!global.stats_fe->bind_proc) | |||
- global.stats_fe->bind_proc = ~0UL; | |||
- } | |||
- | |||
- /* propagate bindings from frontends to backends */ | |||
- for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
- if (curproxy->cap & PR_CAP_FE) | |||
- propagate_processes(curproxy, NULL); | |||
- } | |||
- | |||
- /* Bind each unbound backend to all processes when not specified. */ | |||
- for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
- if (curproxy->bind_proc) | |||
- continue; | |||
- curproxy->bind_proc = ~0UL; | |||
} | |||
/* automatically compute fullconn if not set. We must not do it in the | |||
-- | |||
1.8.5.5 | |||
@ -1,45 +0,0 @@ | |||
From 036a83e9c300a42386cd378022420e52a43b314f Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Tue, 16 Sep 2014 15:11:04 +0200 | |||
Subject: [PATCH 11/13] MEDIUM: config: only warn if stats are attached to | |||
multi-process bind directives | |||
Some users want to have a stats frontend with one line per process, but while | |||
100% valid and safe, the config parser emits a warning. Relax this check to | |||
ensure that the warning is only emitted if at least one of the listeners is | |||
bound to multiple processes, or if the directive is placed in a backend called | |||
from multiple processes (since in this case we don't know if it's safe). | |||
(cherry picked from commit eb791e03b5c5abfddb24a439fa6434788db026b7) | |||
--- | |||
src/cfgparse.c | 15 +++++++++++++-- | |||
1 file changed, 13 insertions(+), 2 deletions(-) | |||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||
index f3907bf..5668393 100644 | |||
--- a/src/cfgparse.c | |||
+++ b/src/cfgparse.c | |||
@@ -7189,8 +7189,19 @@ out_uri_auth_compat: | |||
if (nbproc > 1) { | |||
if (curproxy->uri_auth) { | |||
- Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n", | |||
- curproxy->id); | |||
+ int count, maxproc = 0; | |||
+ | |||
+ list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) { | |||
+ count = popcount(bind_conf->bind_proc); | |||
+ if (count > maxproc) | |||
+ maxproc = count; | |||
+ } | |||
+ /* backends have 0, frontends have 1 or more */ | |||
+ if (maxproc != 1) | |||
+ Warning("Proxy '%s': in multi-process mode, stats will be" | |||
+ " limited to process assigned to the current request.\n", | |||
+ curproxy->id); | |||
+ | |||
if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) { | |||
Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n", | |||
curproxy->id); | |||
-- | |||
1.8.5.5 | |||
@ -1,110 +0,0 @@ | |||
From 8b3c808c37dd5672f87e7b61085295e1316a6694 Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Tue, 16 Sep 2014 15:39:51 +0200 | |||
Subject: [PATCH 12/13] MEDIUM: config: report it when tcp-request rules are | |||
misplaced | |||
A config where a tcp-request rule appears after an http-request rule | |||
might seem valid but it is not. So let's report a warning about this | |||
since this case is hard to detect by the naked eye. | |||
(cherry picked from commit 3986b9c14037f446f5f5bec6207a39e1bd753fae) | |||
--- | |||
include/common/cfgparse.h | 2 ++ | |||
src/cfgparse.c | 38 ++++++++++++++++++++++++++++++++++++++ | |||
src/proto_tcp.c | 4 ++++ | |||
3 files changed, 44 insertions(+) | |||
diff --git a/include/common/cfgparse.h b/include/common/cfgparse.h | |||
index 80310ae..86a0035 100644 | |||
--- a/include/common/cfgparse.h | |||
+++ b/include/common/cfgparse.h | |||
@@ -73,6 +73,8 @@ int check_config_validity(); | |||
int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err); | |||
int cfg_register_section(char *section_name, | |||
int (*section_parser)(const char *, int, char **, int)); | |||
+int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg); | |||
+int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg); | |||
/* | |||
* Sends a warning if proxy <proxy> does not have at least one of the | |||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||
index 5668393..9ff44e9 100644 | |||
--- a/src/cfgparse.c | |||
+++ b/src/cfgparse.c | |||
@@ -317,6 +317,19 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, | |||
return 0; | |||
} | |||
+/* Report a warning if a rule is placed after a 'tcp-request content' rule. | |||
+ * Return 1 if the warning has been emitted, otherwise 0. | |||
+ */ | |||
+int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg) | |||
+{ | |||
+ if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) { | |||
+ Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n", | |||
+ file, line, arg); | |||
+ return 1; | |||
+ } | |||
+ return 0; | |||
+} | |||
+ | |||
/* Report a warning if a rule is placed after a 'block' rule. | |||
* Return 1 if the warning has been emitted, otherwise 0. | |||
*/ | |||
@@ -408,6 +421,31 @@ int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line | |||
return 0; | |||
} | |||
+/* report a warning if a "tcp request connection" rule is dangerously placed */ | |||
+int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg) | |||
+{ | |||
+ return warnif_rule_after_tcp_cont(proxy, file, line, arg) || | |||
+ warnif_rule_after_block(proxy, file, line, arg) || | |||
+ warnif_rule_after_http_req(proxy, file, line, arg) || | |||
+ warnif_rule_after_reqxxx(proxy, file, line, arg) || | |||
+ warnif_rule_after_reqadd(proxy, file, line, arg) || | |||
+ warnif_rule_after_redirect(proxy, file, line, arg) || | |||
+ warnif_rule_after_use_backend(proxy, file, line, arg) || | |||
+ warnif_rule_after_use_server(proxy, file, line, arg); | |||
+} | |||
+ | |||
+/* report a warning if a "tcp request content" rule is dangerously placed */ | |||
+int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg) | |||
+{ | |||
+ return warnif_rule_after_block(proxy, file, line, arg) || | |||
+ warnif_rule_after_http_req(proxy, file, line, arg) || | |||
+ warnif_rule_after_reqxxx(proxy, file, line, arg) || | |||
+ warnif_rule_after_reqadd(proxy, file, line, arg) || | |||
+ warnif_rule_after_redirect(proxy, file, line, arg) || | |||
+ warnif_rule_after_use_backend(proxy, file, line, arg) || | |||
+ warnif_rule_after_use_server(proxy, file, line, arg); | |||
+} | |||
+ | |||
/* report a warning if a block rule is dangerously placed */ | |||
int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg) | |||
{ | |||
diff --git a/src/proto_tcp.c b/src/proto_tcp.c | |||
index 72dc92b..940c3f1 100644 | |||
--- a/src/proto_tcp.c | |||
+++ b/src/proto_tcp.c | |||
@@ -1711,6 +1711,8 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx, | |||
warn++; | |||
} | |||
+ /* the following function directly emits the warning */ | |||
+ warnif_misplaced_tcp_cont(curpx, file, line, args[0]); | |||
LIST_ADDQ(&curpx->tcp_req.inspect_rules, &rule->list); | |||
} | |||
else if (strcmp(args[1], "connection") == 0) { | |||
@@ -1754,6 +1756,8 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx, | |||
warn++; | |||
} | |||
+ /* the following function directly emits the warning */ | |||
+ warnif_misplaced_tcp_conn(curpx, file, line, args[0]); | |||
LIST_ADDQ(&curpx->tcp_req.l4_rules, &rule->list); | |||
} | |||
else { | |||
-- | |||
1.8.5.5 | |||
@ -1,52 +0,0 @@ | |||
From 7fc7ebd5785629074297ee324b22e0aee9ad00f9 Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Tue, 16 Sep 2014 16:21:19 +0200 | |||
Subject: [PATCH 13/13] MINOR: config: detect the case where a tcp-request | |||
content rule has no inspect-delay | |||
If a frontend has any tcp-request content rule relying on request contents | |||
without any inspect delay, we now emit a warning as this will randomly match. | |||
This can be backported to 1.5 as it reduces the support effort. | |||
(cherry picked from commit e42bd96d0acc38ea7c546c8de8115ffd1dd6c3f3) | |||
--- | |||
src/cfgparse.c | 23 +++++++++++++++++++++++ | |||
1 file changed, 23 insertions(+) | |||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||
index 9ff44e9..f723a3a 100644 | |||
--- a/src/cfgparse.c | |||
+++ b/src/cfgparse.c | |||
@@ -6998,6 +6998,29 @@ out_uri_auth_compat: | |||
newsrv = newsrv->next; | |||
} | |||
+ /* check if we have a frontend with "tcp-request content" looking at L7 | |||
+ * with no inspect-delay | |||
+ */ | |||
+ if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) { | |||
+ list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) { | |||
+ if (trule->action == TCP_ACT_CAPTURE && | |||
+ !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC)) | |||
+ break; | |||
+ if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) && | |||
+ !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC)) | |||
+ break; | |||
+ } | |||
+ | |||
+ if (&trule->list != &curproxy->tcp_req.inspect_rules) { | |||
+ Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request" | |||
+ " contents were found in a frontend without any 'tcp-request inspect-delay' setting." | |||
+ " This means that these rules will randomly find their contents. This can be fixed by" | |||
+ " setting the tcp-request inspect-delay.\n", | |||
+ proxy_type_str(curproxy), curproxy->id); | |||
+ err_code |= ERR_WARN; | |||
+ } | |||
+ } | |||
+ | |||
if (curproxy->cap & PR_CAP_FE) { | |||
if (!curproxy->accept) | |||
curproxy->accept = frontend_accept; | |||
-- | |||
1.8.5.5 | |||
@ -1,90 +0,0 @@ | |||
From afbfc27c0f2cac29e18f87b36335ea821c633b9d Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Fri, 19 Sep 2014 15:42:30 +0200 | |||
Subject: [PATCH 14/14] MEDIUM: systemd-wrapper: support multiple executable | |||
versions and names | |||
Having to use a hard-coded "haproxy" executable name next to the systemd | |||
wrapper is not always convenient, as it's sometimes desirable to run with | |||
multiple versions in parallel. | |||
Thus this patch performs a minor change to the wrapper : if the name ends | |||
with "-systemd-wrapper", then it trims that part off and what remains | |||
becomes the target haproxy executable. That makes it easy to have for | |||
example : | |||
haproxy-1.5.4-systemd-wrapper haproxy-1.5.4 | |||
haproxy-1.5.3-systemd-wrapper haproxy-1.5.3 | |||
and so on, in a same directory. | |||
This patch also fixes a rare bug caused by readlink() not adding the | |||
trailing zero and leaving possible existing contents, including possibly | |||
a randomly placed "/" which would make it unable to locate the correct | |||
binary. This case is not totally unlikely as I got a \177 a few times | |||
at the end of the executable names, so I could have got a '/' as well. | |||
Back-porting to 1.5 is desirable. | |||
(cherry picked from commit ceaf2aec1ec1612da461c61798e944693144bee9) | |||
--- | |||
src/haproxy-systemd-wrapper.c | 27 ++++++++++++++++++++++----- | |||
1 file changed, 22 insertions(+), 5 deletions(-) | |||
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c | |||
index cc8baa8..446f28f 100644 | |||
--- a/src/haproxy-systemd-wrapper.c | |||
+++ b/src/haproxy-systemd-wrapper.c | |||
@@ -28,20 +28,36 @@ static char *pid_file = "/run/haproxy.pid"; | |||
static int wrapper_argc; | |||
static char **wrapper_argv; | |||
+/* returns the path to the haproxy binary into <buffer>, whose size indicated | |||
+ * in <buffer_size> must be at least 1 byte long. | |||
+ */ | |||
static void locate_haproxy(char *buffer, size_t buffer_size) | |||
{ | |||
char *end = NULL; | |||
+ int len; | |||
+ | |||
+ len = readlink("/proc/self/exe", buffer, buffer_size - 1); | |||
+ if (len == -1) | |||
+ goto fail; | |||
- if (readlink("/proc/self/exe", buffer, buffer_size) > 0) | |||
- end = strrchr(buffer, '/'); | |||
+ buffer[len] = 0; | |||
+ end = strrchr(buffer, '/'); | |||
+ if (end == NULL) | |||
+ goto fail; | |||
- if (end == NULL) { | |||
- strncpy(buffer, "/usr/sbin/haproxy", buffer_size); | |||
+ if (strcmp(end + strlen(end) - 16, "-systemd-wrapper") == 0) { | |||
+ end[strlen(end) - 16] = '\0'; | |||
return; | |||
} | |||
+ | |||
end[1] = '\0'; | |||
strncpy(end + 1, "haproxy", buffer + buffer_size - (end + 1)); | |||
buffer[buffer_size - 1] = '\0'; | |||
+ return; | |||
+ fail: | |||
+ strncpy(buffer, "/usr/sbin/haproxy", buffer_size); | |||
+ buffer[buffer_size - 1] = '\0'; | |||
+ return; | |||
} | |||
static void spawn_haproxy(char **pid_strv, int nb_pid) | |||
@@ -54,7 +70,8 @@ static void spawn_haproxy(char **pid_strv, int nb_pid) | |||
main_argc = wrapper_argc - 1; | |||
main_argv = wrapper_argv + 1; | |||
- pid = fork(); | |||
+ //pid = fork(); | |||
+ pid=0; | |||
if (!pid) { | |||
/* 3 for "haproxy -Ds -sf" */ | |||
char **argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *)); | |||
-- | |||
1.8.5.5 | |||
@ -1,36 +0,0 @@ | |||
From 575e299cc07f5f2b314d91dfac8671834cbdd2a7 Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Wed, 24 Sep 2014 12:59:25 +0200 | |||
Subject: [PATCH 15/20] BUG/MEDIUM: remove debugging code from systemd-wrapper | |||
MIME-Version: 1.0 | |||
Content-Type: text/plain; charset=UTF-8 | |||
Content-Transfer-Encoding: 8bit | |||
Kristoffer Grönlund reported that after my recent update to the | |||
systemd-wrapper, I accidentely left the debugging code which | |||
consists in disabling the fork :-( | |||
The fix needs to be backported to 1.5 as well since I pushed it | |||
there as well. | |||
(cherry picked from commit a55bbc64d8272e4066a67b6d190ffebaff2b300a) | |||
--- | |||
src/haproxy-systemd-wrapper.c | 3 +-- | |||
1 file changed, 1 insertion(+), 2 deletions(-) | |||
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c | |||
index 446f28f..8602881 100644 | |||
--- a/src/haproxy-systemd-wrapper.c | |||
+++ b/src/haproxy-systemd-wrapper.c | |||
@@ -70,8 +70,7 @@ static void spawn_haproxy(char **pid_strv, int nb_pid) | |||
main_argc = wrapper_argc - 1; | |||
main_argv = wrapper_argv + 1; | |||
- //pid = fork(); | |||
- pid=0; | |||
+ pid = fork(); | |||
if (!pid) { | |||
/* 3 for "haproxy -Ds -sf" */ | |||
char **argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *)); | |||
-- | |||
2.0.4 | |||
@ -1,188 +0,0 @@ | |||
From 2e47a3ab11188239abadb6bba7bd901d764aa4fb Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Tue, 30 Sep 2014 18:44:22 +0200 | |||
Subject: [PATCH 16/20] BUG/MEDIUM: http: adjust close mode when switching to | |||
backend | |||
Commit 179085c ("MEDIUM: http: move Connection header processing earlier") | |||
introduced a regression : the backend's HTTP mode is not considered anymore | |||
when setting the session's HTTP mode, because wait_for_request() is only | |||
called once, when the frontend receives the request (or when the frontend | |||
is in TCP mode, when the backend receives the request). | |||
The net effect is that in some situations when the frontend and the backend | |||
do not work in the same mode (eg: keep-alive vs close), the backend's mode | |||
is ignored. | |||
This patch moves all that processing to a dedicated function, which is | |||
called from the original place, as well as from session_set_backend() | |||
when switching from an HTTP frontend to an HTTP backend in different | |||
modes. | |||
This fix must be backported to 1.5. | |||
(cherry picked from commit 4e21ff9244aefa56bcf0793a9e07edba2c3c1960) | |||
--- | |||
include/proto/proto_http.h | 1 + | |||
src/proto_http.c | 107 +++++++++++++++++++++++---------------------- | |||
src/proxy.c | 8 ++++ | |||
3 files changed, 64 insertions(+), 52 deletions(-) | |||
diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h | |||
index e898ca8..8014310 100644 | |||
--- a/include/proto/proto_http.h | |||
+++ b/include/proto/proto_http.h | |||
@@ -112,6 +112,7 @@ unsigned int http_get_hdr(const struct http_msg *msg, const char *hname, int hle | |||
void http_init_txn(struct session *s); | |||
void http_end_txn(struct session *s); | |||
void http_reset_txn(struct session *s); | |||
+void http_adjust_conn_mode(struct session *s, struct http_txn *txn, struct http_msg *msg); | |||
struct http_req_rule *parse_http_req_cond(const char **args, const char *file, int linenum, struct proxy *proxy); | |||
struct http_res_rule *parse_http_res_cond(const char **args, const char *file, int linenum, struct proxy *proxy); | |||
diff --git a/src/proto_http.c b/src/proto_http.c | |||
index 7e35c8b..20e7088 100644 | |||
--- a/src/proto_http.c | |||
+++ b/src/proto_http.c | |||
@@ -2393,6 +2393,59 @@ fail: | |||
return 0; | |||
} | |||
+void http_adjust_conn_mode(struct session *s, struct http_txn *txn, struct http_msg *msg) | |||
+{ | |||
+ int tmp = TX_CON_WANT_KAL; | |||
+ | |||
+ if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) { | |||
+ if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN || | |||
+ (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN) | |||
+ tmp = TX_CON_WANT_TUN; | |||
+ | |||
+ if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL || | |||
+ (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL) | |||
+ tmp = TX_CON_WANT_TUN; | |||
+ } | |||
+ | |||
+ if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL || | |||
+ (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) { | |||
+ /* option httpclose + server_close => forceclose */ | |||
+ if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL || | |||
+ (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL) | |||
+ tmp = TX_CON_WANT_CLO; | |||
+ else | |||
+ tmp = TX_CON_WANT_SCL; | |||
+ } | |||
+ | |||
+ if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL || | |||
+ (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL) | |||
+ tmp = TX_CON_WANT_CLO; | |||
+ | |||
+ if ((txn->flags & TX_CON_WANT_MSK) < tmp) | |||
+ txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp; | |||
+ | |||
+ if (!(txn->flags & TX_HDR_CONN_PRS) && | |||
+ (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) { | |||
+ /* parse the Connection header and possibly clean it */ | |||
+ int to_del = 0; | |||
+ if ((msg->flags & HTTP_MSGF_VER_11) || | |||
+ ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL && | |||
+ !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA))) | |||
+ to_del |= 2; /* remove "keep-alive" */ | |||
+ if (!(msg->flags & HTTP_MSGF_VER_11)) | |||
+ to_del |= 1; /* remove "close" */ | |||
+ http_parse_connection_header(txn, msg, to_del); | |||
+ } | |||
+ | |||
+ /* check if client or config asks for explicit close in KAL/SCL */ | |||
+ if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL || | |||
+ (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) && | |||
+ ((txn->flags & TX_HDR_CONN_CLO) || /* "connection: close" */ | |||
+ (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */ | |||
+ !(msg->flags & HTTP_MSGF_XFER_LEN) || /* no length known => close */ | |||
+ s->fe->state == PR_STSTOPPED)) /* frontend is stopping */ | |||
+ txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO; | |||
+} | |||
/* This stream analyser waits for a complete HTTP request. It returns 1 if the | |||
* processing can continue on next analysers, or zero if it either needs more | |||
@@ -2929,58 +2982,8 @@ int http_wait_for_request(struct session *s, struct channel *req, int an_bit) | |||
* time. | |||
*/ | |||
if (!(txn->flags & TX_HDR_CONN_PRS) || | |||
- ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE))) { | |||
- int tmp = TX_CON_WANT_KAL; | |||
- | |||
- if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) { | |||
- if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN || | |||
- (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN) | |||
- tmp = TX_CON_WANT_TUN; | |||
- | |||
- if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL || | |||
- (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL) | |||
- tmp = TX_CON_WANT_TUN; | |||
- } | |||
- | |||
- if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL || | |||
- (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) { | |||
- /* option httpclose + server_close => forceclose */ | |||
- if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL || | |||
- (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL) | |||
- tmp = TX_CON_WANT_CLO; | |||
- else | |||
- tmp = TX_CON_WANT_SCL; | |||
- } | |||
- | |||
- if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL || | |||
- (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL) | |||
- tmp = TX_CON_WANT_CLO; | |||
- | |||
- if ((txn->flags & TX_CON_WANT_MSK) < tmp) | |||
- txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp; | |||
- | |||
- if (!(txn->flags & TX_HDR_CONN_PRS) && | |||
- (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) { | |||
- /* parse the Connection header and possibly clean it */ | |||
- int to_del = 0; | |||
- if ((msg->flags & HTTP_MSGF_VER_11) || | |||
- ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL && | |||
- !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA))) | |||
- to_del |= 2; /* remove "keep-alive" */ | |||
- if (!(msg->flags & HTTP_MSGF_VER_11)) | |||
- to_del |= 1; /* remove "close" */ | |||
- http_parse_connection_header(txn, msg, to_del); | |||
- } | |||
- | |||
- /* check if client or config asks for explicit close in KAL/SCL */ | |||
- if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL || | |||
- (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) && | |||
- ((txn->flags & TX_HDR_CONN_CLO) || /* "connection: close" */ | |||
- (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */ | |||
- !(msg->flags & HTTP_MSGF_XFER_LEN) || /* no length known => close */ | |||
- s->fe->state == PR_STSTOPPED)) /* frontend is stopping */ | |||
- txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO; | |||
- } | |||
+ ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE))) | |||
+ http_adjust_conn_mode(s, txn, msg); | |||
/* end of job, return OK */ | |||
req->analysers &= ~an_bit; | |||
diff --git a/src/proxy.c b/src/proxy.c | |||
index 02103ee..405c4c4 100644 | |||
--- a/src/proxy.c | |||
+++ b/src/proxy.c | |||
@@ -955,6 +955,14 @@ int session_set_backend(struct session *s, struct proxy *be) | |||
http_init_txn(s); | |||
} | |||
+ /* If we chain to an HTTP backend running a different HTTP mode, we | |||
+ * have to re-adjust the desired keep-alive/close mode to accommodate | |||
+ * both the frontend's and the backend's modes. | |||
+ */ | |||
+ if (s->fe->mode == PR_MODE_HTTP && be->mode == PR_MODE_HTTP && | |||
+ ((s->fe->options & PR_O_HTTP_MODE) != (be->options & PR_O_HTTP_MODE))) | |||
+ http_adjust_conn_mode(s, &s->txn, &s->txn.req); | |||
+ | |||
/* If an LB algorithm needs to access some pre-parsed body contents, | |||
* we must not start to forward anything until the connection is | |||
* confirmed otherwise we'll lose the pointer to these data and | |||
-- | |||
2.0.4 | |||
@ -1,46 +0,0 @@ | |||
From b3228c83e320ad168f5b3e6884e771530a68a449 Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Wed, 1 Oct 2014 20:50:17 +0200 | |||
Subject: [PATCH 17/20] BUG/MINOR: config: don't propagate process binding on | |||
fatal errors. | |||
propagate_processes() must not be called with unresolved proxies, but | |||
nothing prevents it from being called in check_config_validity(). The | |||
resulting effect is that an unresolved proxy can cause a recursion | |||
loop if called in such a situation, ending with a segfault after the | |||
fatal error report. There's no side effect beyond this. | |||
This patch refrains from calling the function when any error was met. | |||
This bug also affects 1.5, it should be backported. | |||
(cherry picked from commit acbe8ab38a638a076f8cf9fe2635db0e729d6a1f) | |||
--- | |||
src/cfgparse.c | 12 ++++++++---- | |||
1 file changed, 8 insertions(+), 4 deletions(-) | |||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||
index f723a3a..6e962c8 100644 | |||
--- a/src/cfgparse.c | |||
+++ b/src/cfgparse.c | |||
@@ -7112,10 +7112,14 @@ out_uri_auth_compat: | |||
global.stats_fe->bind_proc = ~0UL; | |||
} | |||
- /* propagate bindings from frontends to backends */ | |||
- for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
- if (curproxy->cap & PR_CAP_FE) | |||
- propagate_processes(curproxy, NULL); | |||
+ /* propagate bindings from frontends to backends. Don't do it if there | |||
+ * are any fatal errors as we must not call it with unresolved proxies. | |||
+ */ | |||
+ if (!cfgerr) { | |||
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) { | |||
+ if (curproxy->cap & PR_CAP_FE) | |||
+ propagate_processes(curproxy, NULL); | |||
+ } | |||
} | |||
/* Bind each unbound backend to all processes when not specified. */ | |||
-- | |||
2.0.4 | |||
@ -1,102 +0,0 @@ | |||
From e61737a721c3b91c79484e51fc1789293b269f9f Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Thu, 2 Oct 2014 14:30:14 +0200 | |||
Subject: [PATCH 18/20] BUG/MEDIUM: check: rule-less tcp-check must detect | |||
connect failures | |||
When "option tcp-check" is specified without any tcp-check rules, the | |||
documentation says that it's the same as the default check method. But | |||
the code path is a bit different, and we used to consider that since | |||
the end of rules was reached, the check is always successful regardless | |||
of the connection status. | |||
This patch reorganizes the error detection, and considers the special | |||
case where there's no tcp-check rule as a real L4 check. It also avoids | |||
dereferencing the rule list head as a rule by itself. | |||
While fixing this bug, another one related to the output messages' | |||
accuracy was noticed, it will be fixed in a separate commit and is | |||
much less important. | |||
This bug is also present in 1.5, so this fix must be backported. | |||
(cherry picked from commit ef953953e7f33c6a72c432fce8d47c2d84c69512) | |||
--- | |||
src/checks.c | 40 +++++++++++++++++++++++++--------------- | |||
1 file changed, 25 insertions(+), 15 deletions(-) | |||
diff --git a/src/checks.c b/src/checks.c | |||
index f3b2b54..9c1a866 100644 | |||
--- a/src/checks.c | |||
+++ b/src/checks.c | |||
@@ -1837,20 +1837,34 @@ static int tcpcheck_get_step_id(struct server *s) | |||
static void tcpcheck_main(struct connection *conn) | |||
{ | |||
char *contentptr; | |||
- struct list *head = NULL; | |||
struct tcpcheck_rule *cur = NULL; | |||
int done = 0, ret = 0; | |||
- | |||
struct check *check = conn->owner; | |||
struct server *s = check->server; | |||
struct task *t = check->task; | |||
+ struct list *head = &s->proxy->tcpcheck_rules; | |||
- /* | |||
- * don't do anything until the connection is established but if we're running | |||
- * first step which must be a connect | |||
+ /* here, we know that the check is complete or that it failed */ | |||
+ if (check->result != CHK_RES_UNKNOWN) | |||
+ goto out_end_tcpcheck; | |||
+ | |||
+ /* We have 4 possibilities here : | |||
+ * 1. we've not yet attempted step 1, and step 1 is a connect, so no | |||
+ * connection attempt was made yet ; | |||
+ * 2. we've not yet attempted step 1, and step 1 is a not connect or | |||
+ * does not exist (no rule), so a connection attempt was made | |||
+ * before coming here. | |||
+ * 3. we're coming back after having started with step 1, so we may | |||
+ * be waiting for a connection attempt to complete. | |||
+ * 4. the connection + handshake are complete | |||
+ * | |||
+ * #2 and #3 are quite similar, we want both the connection and the | |||
+ * handshake to complete before going any further. Thus we must always | |||
+ * wait for a connection to complete unless we're before and existing | |||
+ * step 1. | |||
*/ | |||
- if (check->current_step && (!(conn->flags & CO_FL_CONNECTED))) { | |||
- /* update expire time, should be done by process_chk */ | |||
+ if ((!(conn->flags & CO_FL_CONNECTED) || (conn->flags & CO_FL_HANDSHAKE)) && | |||
+ (check->current_step || LIST_ISEMPTY(head))) { | |||
/* we allow up to min(inter, timeout.connect) for a connection | |||
* to establish but only when timeout.check is set | |||
* as it may be to short for a full check otherwise | |||
@@ -1867,12 +1881,11 @@ static void tcpcheck_main(struct connection *conn) | |||
return; | |||
} | |||
- /* here, we know that the connection is established */ | |||
- if (check->result != CHK_RES_UNKNOWN) | |||
+ /* special case: option tcp-check with no rule, a connect is enough */ | |||
+ if (LIST_ISEMPTY(head)) { | |||
+ set_server_check_status(check, HCHK_STATUS_L4OK, NULL); | |||
goto out_end_tcpcheck; | |||
- | |||
- /* head is be the first element of the double chained list */ | |||
- head = &s->proxy->tcpcheck_rules; | |||
+ } | |||
/* no step means first step | |||
* initialisation */ | |||
@@ -1891,9 +1904,6 @@ static void tcpcheck_main(struct connection *conn) | |||
cur = check->current_step; | |||
} | |||
- if (conn->flags & CO_FL_HANDSHAKE) | |||
- return; | |||
- | |||
/* It's only the rules which will enable send/recv */ | |||
__conn_data_stop_both(conn); | |||
-- | |||
2.0.4 | |||
@ -1,111 +0,0 @@ | |||
From 90055f28a7a0c86cfb37ccb23a548a1da7229551 Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Thu, 2 Oct 2014 14:51:02 +0200 | |||
Subject: [PATCH 19/20] BUG/MINOR: tcp-check: report the correct failed step in | |||
the status | |||
The step number was reported by checking only last_started_step, which | |||
was not set in case of error during the initial connection phase, and | |||
caused "step 1" to be returned with an invalid check type (typically | |||
SEND). So now we first verify that a test was started before returning | |||
this. | |||
In addition to this, the indication of the test type was taken from | |||
current_step instead of last_started_step, so the error description | |||
was matching the next action instead of the one reported in the step | |||
ID. Thus we could get the confusing "step 1 (send)" report below : | |||
tcp-check connect | |||
tcp-check send foo | |||
In order to ease debugging, when the port number is known for a connect, | |||
it is indicated in the error report. | |||
Note that this only affects asynchronous error messages, synchronous ones | |||
are correct. | |||
This fix must be backported to 1.5. | |||
(cherry picked from commit 213c6785614d0228d7e96e982e5189e1d0777059) | |||
--- | |||
src/checks.c | 43 ++++++++++++++++++++++++++++--------------- | |||
1 file changed, 28 insertions(+), 15 deletions(-) | |||
diff --git a/src/checks.c b/src/checks.c | |||
index 9c1a866..5318f35 100644 | |||
--- a/src/checks.c | |||
+++ b/src/checks.c | |||
@@ -580,6 +580,7 @@ static void chk_report_conn_err(struct connection *conn, int errno_bck, int expi | |||
struct check *check = conn->owner; | |||
const char *err_msg; | |||
struct chunk *chk; | |||
+ int step; | |||
if (check->result != CHK_RES_UNKNOWN) | |||
return; | |||
@@ -599,19 +600,27 @@ static void chk_report_conn_err(struct connection *conn, int errno_bck, int expi | |||
chk = get_trash_chunk(); | |||
if (check->type == PR_O2_TCPCHK_CHK) { | |||
- chunk_printf(chk, " at step %d of tcp-check", tcpcheck_get_step_id(check->server)); | |||
- /* we were looking for a string */ | |||
- if (check->current_step && check->current_step->action == TCPCHK_ACT_CONNECT) { | |||
- chunk_appendf(chk, " (connect)"); | |||
- } | |||
- else if (check->current_step && check->current_step->action == TCPCHK_ACT_EXPECT) { | |||
- if (check->current_step->string) | |||
- chunk_appendf(chk, " (string '%s')", check->current_step->string); | |||
- else if (check->current_step->expect_regex) | |||
- chunk_appendf(chk, " (expect regex)"); | |||
- } | |||
- else if (check->current_step && check->current_step->action == TCPCHK_ACT_SEND) { | |||
- chunk_appendf(chk, " (send)"); | |||
+ step = tcpcheck_get_step_id(check->server); | |||
+ if (!step) | |||
+ chunk_printf(chk, " at initial connection step of tcp-check"); | |||
+ else { | |||
+ chunk_printf(chk, " at step %d of tcp-check", step); | |||
+ /* we were looking for a string */ | |||
+ if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_CONNECT) { | |||
+ if (check->last_started_step->port) | |||
+ chunk_appendf(chk, " (connect port %d)" ,check->last_started_step->port); | |||
+ else | |||
+ chunk_appendf(chk, " (connect)"); | |||
+ } | |||
+ else if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_EXPECT) { | |||
+ if (check->last_started_step->string) | |||
+ chunk_appendf(chk, " (string '%s')", check->last_started_step->string); | |||
+ else if (check->last_started_step->expect_regex) | |||
+ chunk_appendf(chk, " (expect regex)"); | |||
+ } | |||
+ else if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_SEND) { | |||
+ chunk_appendf(chk, " (send)"); | |||
+ } | |||
} | |||
} | |||
@@ -1818,6 +1827,10 @@ static int tcpcheck_get_step_id(struct server *s) | |||
struct tcpcheck_rule *cur = NULL, *next = NULL; | |||
int i = 0; | |||
+ /* not even started anything yet => step 0 = initial connect */ | |||
+ if (!s->check.current_step) | |||
+ return 0; | |||
+ | |||
cur = s->check.last_started_step; | |||
/* no step => first step */ | |||
@@ -1887,9 +1900,9 @@ static void tcpcheck_main(struct connection *conn) | |||
goto out_end_tcpcheck; | |||
} | |||
- /* no step means first step | |||
- * initialisation */ | |||
+ /* no step means first step initialisation */ | |||
if (check->current_step == NULL) { | |||
+ check->last_started_step = NULL; | |||
check->bo->p = check->bo->data; | |||
check->bo->o = 0; | |||
check->bi->p = check->bi->data; | |||
-- | |||
2.0.4 | |||
@ -1,34 +0,0 @@ | |||
From c8d57dec6173430bd5602bb76efff302c51e7803 Mon Sep 17 00:00:00 2001 | |||
From: =?UTF-8?q?Cyril=20Bont=C3=A9?= <cyril.bonte@free.fr> | |||
Date: Thu, 2 Oct 2014 19:56:25 +0200 | |||
Subject: [PATCH 20/20] BUG/MINOR: config: don't propagate process binding for | |||
dynamic use_backend | |||
A segfault was reported with the introduction of the propagate_processes() | |||
function. It was caused when a use_backend rule was declared with a dynamic | |||
name, using a log-format string. The backend is not resolved during the | |||
configuration, which lead to the segfault. | |||
The patch prevents the process binding propagation for such dynamic rules, it | |||
should also be backported to 1.5. | |||
(cherry picked from commit 51639696e0a112ea3612e905a5722ad912b3869f) | |||
--- | |||
src/cfgparse.c | 2 ++ | |||
1 file changed, 2 insertions(+) | |||
diff --git a/src/cfgparse.c b/src/cfgparse.c | |||
index 6e962c8..ec6d923 100644 | |||
--- a/src/cfgparse.c | |||
+++ b/src/cfgparse.c | |||
@@ -6015,6 +6015,8 @@ void propagate_processes(struct proxy *from, struct proxy *to) | |||
/* use_backend */ | |||
list_for_each_entry(rule, &from->switching_rules, list) { | |||
+ if (rule->dynamic) | |||
+ continue; | |||
to = rule->be.backend; | |||
propagate_processes(from, to); | |||
} | |||
-- | |||
2.0.4 | |||