|
|
- 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
-
|