From 7df8ca6296e7f2af2cadf05830af54b998e9c196 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 15 Jul 2019 10:57:51 +0200 Subject: [PATCH] BUG/MEDIUM: tcp-check: unbreak multiple connect rules again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The last connect rule used to be ignored and that was fixed by commit 248f1173f ("BUG/MEDIUM: tcp-check: single connect rule can't detect DOWN servers") during 1.9 development. However this patch went a bit too far by not breaking out of the loop after a pending connect(), resulting in a series of failed connect() to be quickly skipped and only the last one to be taken into account. Technically speaking the series is not exactly skipped, it's just that TCP checks suffer from a design issue which is that there is no distinction between a new rule and this rule's completion in the "connect" rule handling code. As such, when evaluating TCPCHK_ACT_CONNECT a new connection is created regardless of any previous connection in progress, and the previous result is ignored. It seems that this issue is mostly specific to the connect action if we refer to the comments at the top of the function, so it might be possible to durably address it by reworking the connect state. For now this patch does something simpler, it restores the behaviour before the commit above consisting in breaking out of the loop when the connection is in progress and after skipping comment rules. This way we fall back to the default code waiting for completion. This patch must be backported as far as 1.8 since the commit above was backported there. Thanks to Jérôme Magnin for reporting and bisecting this issue. --- src/checks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/checks.c b/src/checks.c index a1fe015df4..920311a029 100644 --- a/src/checks.c +++ b/src/checks.c @@ -2960,6 +2960,10 @@ static int tcpcheck_main(struct check *check) if (&check->current_step->list == head) break; + /* don't do anything until the connection is established */ + if (!(conn->flags & CO_FL_CONNECTED)) + break; + } /* end 'connect' */ else if (check->current_step->action == TCPCHK_ACT_SEND) { /* mark the step as started */