From: Christopher Faulet Date: Fri, 14 Apr 2023 08:42:08 +0000 (+0200) Subject: MINOR: stconn: Add a flag to ack endpoint errors at SC level X-Git-Tag: v2.8-dev8~141 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a1d14a7c7f3ec8abcabc0b29e1f30afb0c7ec417;p=thirdparty%2Fhaproxy.git MINOR: stconn: Add a flag to ack endpoint errors at SC level The flag SC_FL_ERROR is added to ack errors on the endpoint. When SE_FL_ERROR flag is detected on the SE descriptor, the corresponding is set on the SC. Idea is to avoid, as far as possible, to manipulated the SE descriptor in upper layers and know when an error in the endpoint is handled by the SC. For now, this flag is only set and cleared but never tested. --- diff --git a/include/haproxy/stconn-t.h b/include/haproxy/stconn-t.h index ce0876ba0f..951b790730 100644 --- a/include/haproxy/stconn-t.h +++ b/include/haproxy/stconn-t.h @@ -142,7 +142,7 @@ enum sc_flags { SC_FL_ISBACK = 0x00000001, /* Set for SC on back-side */ SC_FL_EOI = 0x00000002, /* End of input was reached. no more data will be received from the endpoint */ - /* not used: 0x00000004 */ + SC_FL_ERROR = 0x00000004, /* A fatal error was reported */ SC_FL_NOLINGER = 0x00000008, /* may close without lingering. One-shot. */ SC_FL_NOHALF = 0x00000010, /* no half close, close both sides at once */ @@ -174,11 +174,11 @@ static forceinline char *sc_show_flags(char *buf, size_t len, const char *delim, /* prologue */ _(0); /* flags */ - _(SC_FL_ISBACK, _(SC_FL_EOI, _(SC_FL_NOLINGER, _(SC_FL_NOHALF, + _(SC_FL_ISBACK, _(SC_FL_EOI, _(SC_FL_ERROR, _(SC_FL_NOLINGER, _(SC_FL_NOHALF, _(SC_FL_DONT_WAKE, _(SC_FL_INDEP_STR, _(SC_FL_WONT_READ, _(SC_FL_NEED_BUFF, _(SC_FL_NEED_ROOM, _(SC_FL_RCV_ONCE, _(SC_FL_SND_ASAP, _(SC_FL_SND_NEVERWAIT, _(SC_FL_SND_EXP_MORE, - _(SC_FL_ABRT_WANTED, _(SC_FL_SHUT_WANTED, _(SC_FL_ABRT_DONE, _(SC_FL_SHUT_DONE))))))))))))))))); + _(SC_FL_ABRT_WANTED, _(SC_FL_SHUT_WANTED, _(SC_FL_ABRT_DONE, _(SC_FL_SHUT_DONE)))))))))))))))))); /* epilogue */ _(~0U); return buf; diff --git a/src/cli.c b/src/cli.c index d8c3d44abe..5f859b93d8 100644 --- a/src/cli.c +++ b/src/cli.c @@ -2830,7 +2830,7 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit) sockaddr_free(&s->scb->dst); sc_set_state(s->scb, SC_ST_INI); - s->scb->flags &= ~(SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED); + s->scb->flags &= ~(SC_FL_ERROR|SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED); s->scb->flags &= SC_FL_ISBACK | SC_FL_DONT_WAKE; /* we're in the context of process_stream */ s->req.flags &= ~(CF_AUTO_CONNECT|CF_STREAMER|CF_STREAMER_FAST|CF_WROTE_DATA); @@ -2855,7 +2855,7 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit) s->store_count = 0; s->uniq_id = global.req_count++; - s->scf->flags &= ~(SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED); + s->scf->flags &= ~(SC_FL_ERROR|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED); s->scf->flags &= ~SC_FL_SND_NEVERWAIT; s->scf->flags |= SC_FL_RCV_ONCE; /* one read is usually enough */ diff --git a/src/http_ana.c b/src/http_ana.c index 4ec3a389b9..bc9865a1e0 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -1144,7 +1144,7 @@ static __inline int do_l7_retry(struct stream *s, struct stconn *sc) res->analyse_exp = TICK_ETERNITY; res->total = 0; - s->scb->flags &= ~(SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED); + s->scb->flags &= ~(SC_FL_ERROR|SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED); if (sc_reset_endp(s->scb) < 0) { if (!(s->flags & SF_ERR_MASK)) s->flags |= SF_ERR_INTERNAL; diff --git a/src/stconn.c b/src/stconn.c index ceb429b380..c60afcc393 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -1482,8 +1482,10 @@ static int sc_conn_recv(struct stconn *sc) ret = 1; } - if (sc_ep_test(sc, SE_FL_ERROR)) + if (sc_ep_test(sc, SE_FL_ERROR)) { + sc->flags |= SC_FL_ERROR; ret = 1; + } else if (!(sc->flags & (SC_FL_WONT_READ|SC_FL_NEED_BUFF|SC_FL_NEED_ROOM)) && !(sc->flags & SC_FL_ABRT_DONE)) { /* Subscribe to receive events if we're blocking on I/O */ @@ -1663,6 +1665,8 @@ static int sc_conn_send(struct stconn *sc) if (sc_ep_test(sc, SE_FL_ERROR | SE_FL_ERR_PENDING)) { oc->flags |= CF_WRITE_EVENT; BUG_ON(sc_ep_test(sc, SE_FL_EOS|SE_FL_ERROR|SE_FL_ERR_PENDING) == (SE_FL_EOS|SE_FL_ERR_PENDING)); + if (sc_ep_test(sc, SE_FL_ERROR)) + sc_ep_set(sc, SC_FL_ERROR); return 1; } @@ -1734,8 +1738,10 @@ static int sc_conn_process(struct stconn *sc) */ if (sc->state >= SC_ST_CON) { - if (sc_is_conn_error(sc)) + if (sc_is_conn_error(sc)) { sc_ep_set(sc, SE_FL_ERROR); + sc->flags |= SC_FL_ERROR; + } } /* If we had early data, and the handshake ended, then @@ -1784,6 +1790,9 @@ static int sc_conn_process(struct stconn *sc) ic->flags |= CF_READ_EVENT; } + if (sc_ep_test(sc, SE_FL_ERROR)) + sc->flags |= SC_FL_ERROR; + /* Second step : update the stream connector and channels, try to forward any * pending data, then possibly wake the stream up based on the new * stream connector status. @@ -1836,6 +1845,9 @@ static int sc_applet_process(struct stconn *sc) ic->flags |= CF_READ_EVENT; } + if (sc_ep_test(sc, SE_FL_ERROR)) + sc->flags |= SC_FL_ERROR; + if (sc_ep_test(sc, SE_FL_EOS)) { /* we received a shutdown */ sc_abort(sc);