From: Olivier Houchard Date: Mon, 24 Jun 2019 14:08:08 +0000 (+0200) Subject: BUG/MEDIUM: stream_interface: Don't add SI_FL_ERR the state is < SI_ST_CON. X-Git-Tag: v2.1-dev1~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c31e2cbd28d53210b7184091bb64137c806d7957;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: stream_interface: Don't add SI_FL_ERR the state is < SI_ST_CON. Only add SI_FL_ERR if the stream_interface is connected, or is attempting a connection. We may get there because the stream_interface's tasklet was woken up, but before it actually runs, process_stream() may be called, detect that there were an error, and change the state of the stream_interface to SI_ST_TAR. When the stream_interface's tasklet then run, the connection may still have CO_FL_ERROR, but that error was already accounted for, so just ignore it. This should be backported to 2.0. --- diff --git a/src/stream_interface.c b/src/stream_interface.c index 8f89dbaea6..950f55bd13 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -588,8 +588,14 @@ static int si_cs_process(struct conn_stream *cs) /* First step, report to the stream-int what was detected at the * connection layer : errors and connection establishment. + * Only add SI_FL_ERR if we're connected, or we're attempting to + * connect, we may get there because we got woken up, but only run + * after process_stream() noticed there were an error, and decided + * to retry to connect, the connection may still have CO_FL_ERROR, + * and we don't want to add SI_FL_ERR back */ - if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) + if (si->state >= SI_ST_CON && + (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)) si->flags |= SI_FL_ERR; /* If we had early data, and the handshake ended, then @@ -645,6 +651,14 @@ int si_cs_send(struct conn_stream *cs) return 0; if (conn->flags & CO_FL_ERROR || cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) { + /* We're probably there because the tasklet was woken up, + * but process_stream() ran before, detected there were an + * error and put the si back to SI_ST_TAR. There's still + * CO_FL_ERROR on the connection but we don't want to add + * SI_FL_ERR back, so give up + */ + if (si->state < SI_ST_CON) + return 0; si->flags |= SI_FL_ERR; return 1; } @@ -1126,7 +1140,8 @@ static void stream_int_chk_snd_conn(struct stream_interface *si) if (cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING) || cs->conn->flags & CO_FL_ERROR) { /* Write error on the file descriptor */ - si->flags |= SI_FL_ERR; + if (si->state >= SI_ST_CON) + si->flags |= SI_FL_ERR; goto out_wakeup; }