BUG/MINOR: checks: Handle synchronous connect when a tcpcheck is started

A connection may be synchronously established. In the tcpcheck context, it
may be a problem if several connections come one after another. In this
case, there is no event to close the very first connection before starting
the next one. The checks is thus blocked and timed out, a L7 timeout error
is reported.

To fix the bug, when a tcpcheck is started, we immediately evaluate its
state. Most of time, nothing is performed and we must wait. But it is thus
possible to handle the result of a successfull connection.

This patch should fix the issue #1234. It must be backported as far as 2.2.
This commit is contained in:
Christopher Faulet 2021-05-06 16:01:18 +02:00
parent 30aa0da532
commit 92017a3215

View File

@ -1092,8 +1092,8 @@ struct task *process_chk_conn(struct task *t, void *context, unsigned int state)
{
struct check *check = context;
struct proxy *proxy = check->proxy;
struct conn_stream *cs = check->cs;
struct connection *conn = cs_conn(cs);
struct conn_stream *cs;
struct connection *conn;
int rv;
int expired = tick_is_expired(t->expire, now_ms);
@ -1101,6 +1101,7 @@ struct task *process_chk_conn(struct task *t, void *context, unsigned int state)
if (check->server)
HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
if (!(check->state & CHK_ST_INPROGRESS)) {
/* no check currently running */
if (!expired) /* woke up too early */ {
@ -1128,9 +1129,12 @@ struct task *process_chk_conn(struct task *t, void *context, unsigned int state)
check->current_step = NULL;
tcpcheck_main(check);
goto out_unlock;
expired = 0;
}
else {
cs = check->cs;
conn = cs_conn(cs);
/* there was a test running.
* First, let's check whether there was an uncaught error,
* which can happen on connect timeout or error.
@ -1139,7 +1143,7 @@ struct task *process_chk_conn(struct task *t, void *context, unsigned int state)
/* Here the connection must be defined. Otherwise the
* error would have already been detected
*/
if ((conn->flags & CO_FL_ERROR) || cs->flags & CS_FL_ERROR || expired) {
if ((conn && ((conn->flags & CO_FL_ERROR) || (cs->flags & CS_FL_ERROR))) || expired) {
TRACE_ERROR("report connection error", CHK_EV_TASK_WAKE|CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
chk_report_conn_err(check, 0, expired);
}
@ -1223,7 +1227,6 @@ struct task *process_chk_conn(struct task *t, void *context, unsigned int state)
}
t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(check) + rv));
}
}
reschedule:
while (tick_is_expired(t->expire, now_ms))