haproxy: fixes from upstream
authorThomas Heil <heil@terminal-consulting.de>
Mon, 6 Oct 2014 14:28:36 +0000 (16:28 +0200)
committerThomas Heil <heil@terminal-consulting.de>
Mon, 6 Oct 2014 14:28:36 +0000 (16:28 +0200)
 - [PATCH 15/20] BUG/MEDIUM: remove debugging code from systemd-wrapper
 - [PATCH 16/20] BUG/MEDIUM: http: adjust close mode when switching to
 - [PATCH 17/20] BUG/MINOR: config: don't propagate process binding on
 - [PATCH 18/20] BUG/MEDIUM: check: rule-less tcp-check must detect
 - [PATCH 19/20] BUG/MINOR: tcp-check: report the correct failed step in
 - [PATCH 20/20] BUG/MINOR: config: don't propagate process binding for

Signed-off-by: Thomas Heil <heil@terminal-consulting.de>
net/haproxy/Makefile
net/haproxy/patches/0015-BUG-MEDIUM-remove-debugging-code-from-systemd-wrappe.patch [new file with mode: 0644]
net/haproxy/patches/0016-BUG-MEDIUM-http-adjust-close-mode-when-switching-to-.patch [new file with mode: 0644]
net/haproxy/patches/0017-BUG-MINOR-config-don-t-propagate-process-binding-on-.patch [new file with mode: 0644]
net/haproxy/patches/0018-BUG-MEDIUM-check-rule-less-tcp-check-must-detect-con.patch [new file with mode: 0644]
net/haproxy/patches/0019-BUG-MINOR-tcp-check-report-the-correct-failed-step-i.patch [new file with mode: 0644]
net/haproxy/patches/0020-BUG-MINOR-config-don-t-propagate-process-binding-for.patch [new file with mode: 0644]

index 5f0a8e4992c1d7fc412c438cf50a257a06b09466..4a9f8330767d55ae3f0f0dc5aaad8a5f0b15e601 100644 (file)
@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=haproxy
 PKG_VERSION:=1.5.4
-PKG_RELEASE:=15
+PKG_RELEASE:=20
 PKG_SOURCE:=haproxy-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://haproxy.1wt.eu/download/1.5/src/
 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
diff --git a/net/haproxy/patches/0015-BUG-MEDIUM-remove-debugging-code-from-systemd-wrappe.patch b/net/haproxy/patches/0015-BUG-MEDIUM-remove-debugging-code-from-systemd-wrappe.patch
new file mode 100644 (file)
index 0000000..3accdc4
--- /dev/null
@@ -0,0 +1,36 @@
+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
+
diff --git a/net/haproxy/patches/0016-BUG-MEDIUM-http-adjust-close-mode-when-switching-to-.patch b/net/haproxy/patches/0016-BUG-MEDIUM-http-adjust-close-mode-when-switching-to-.patch
new file mode 100644 (file)
index 0000000..6f1b2c7
--- /dev/null
@@ -0,0 +1,188 @@
+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
+
diff --git a/net/haproxy/patches/0017-BUG-MINOR-config-don-t-propagate-process-binding-on-.patch b/net/haproxy/patches/0017-BUG-MINOR-config-don-t-propagate-process-binding-on-.patch
new file mode 100644 (file)
index 0000000..50c25c8
--- /dev/null
@@ -0,0 +1,46 @@
+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
+
diff --git a/net/haproxy/patches/0018-BUG-MEDIUM-check-rule-less-tcp-check-must-detect-con.patch b/net/haproxy/patches/0018-BUG-MEDIUM-check-rule-less-tcp-check-must-detect-con.patch
new file mode 100644 (file)
index 0000000..3d4b18f
--- /dev/null
@@ -0,0 +1,102 @@
+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
+
diff --git a/net/haproxy/patches/0019-BUG-MINOR-tcp-check-report-the-correct-failed-step-i.patch b/net/haproxy/patches/0019-BUG-MINOR-tcp-check-report-the-correct-failed-step-i.patch
new file mode 100644 (file)
index 0000000..b232671
--- /dev/null
@@ -0,0 +1,111 @@
+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
+
diff --git a/net/haproxy/patches/0020-BUG-MINOR-config-don-t-propagate-process-binding-for.patch b/net/haproxy/patches/0020-BUG-MINOR-config-don-t-propagate-process-binding-for.patch
new file mode 100644 (file)
index 0000000..fab81d9
--- /dev/null
@@ -0,0 +1,34 @@
+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
+