]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: tcp-check: don't initialize then break a connection starting with a comment
authorWilly Tarreau <w@1wt.eu>
Wed, 4 Oct 2017 13:58:52 +0000 (15:58 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 4 Oct 2017 14:13:57 +0000 (16:13 +0200)
The following config :

    backend tcp9000
        option tcp-check
        tcp-check comment "this is a comment"
        tcp-check connect port 10000
        server srv 127.0.0.1:9000 check inter 1s

will result in a connection being first made to port 9000 then immediately
destroyed and re-created on port 10000, because the first rule is a comment
and doesn't match the test for the first rule being a connect(). It's
mostly harmless (unless the server really must not receive empty
connections) and the workaround simply consists in removing the comment.

Let's proceed like in other places where we simply skip leading comments.
A new function was made to make this lookup les boring. The fix should be
backported to 1.7 and 1.6.

src/checks.c

index 04780de257143f114232be924d1acf59feffbb28..01059bb92567547038a1500ec1557447df37307d 100644 (file)
@@ -1447,6 +1447,20 @@ static struct task *server_warmup(struct task *t)
        return t;
 }
 
+/* returns the first NON-COMMENT tcp-check rule from list <list> or NULL if
+ * none was found.
+ */
+static struct tcpcheck_rule *get_first_tcpcheck_rule(struct list *list)
+{
+       struct tcpcheck_rule *r;
+
+       list_for_each_entry(r, list, list) {
+               if (r->action != TCPCHK_ACT_COMMENT)
+                       return r;
+       }
+       return NULL;
+}
+
 /*
  * establish a server health-check that makes use of a connection.
  *
@@ -1544,18 +1558,18 @@ static int connect_conn_chk(struct task *t)
        /* only plain tcp-check supports quick ACK */
        quickack = check->type == 0 || check->type == PR_O2_TCPCHK_CHK;
 
-       if (check->type == PR_O2_TCPCHK_CHK && !LIST_ISEMPTY(check->tcpcheck_rules)) {
-               struct tcpcheck_rule *r;
-
-               r = LIST_NEXT(check->tcpcheck_rules, struct tcpcheck_rule *, list);
+       if (check->type == PR_O2_TCPCHK_CHK) {
+               struct tcpcheck_rule *r = get_first_tcpcheck_rule(check->tcpcheck_rules);
 
-               /* if first step is a 'connect', then tcpcheck_main must run it */
-               if (r->action == TCPCHK_ACT_CONNECT) {
-                       tcpcheck_main(conn);
-                       return SF_ERR_UP;
+               if (r) {
+                       /* if first step is a 'connect', then tcpcheck_main must run it */
+                       if (r->action == TCPCHK_ACT_CONNECT) {
+                               tcpcheck_main(conn);
+                               return SF_ERR_UP;
+                       }
+                       if (r->action == TCPCHK_ACT_EXPECT)
+                               quickack = 0;
                }
-               if (r->action == TCPCHK_ACT_EXPECT)
-                       quickack = 0;
        }
 
        ret = SF_ERR_INTERNAL;