]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stconn: Add a flag to ack endpoint errors at SC level
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 14 Apr 2023 08:42:08 +0000 (10:42 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 14 Apr 2023 15:05:53 +0000 (17:05 +0200)
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.

include/haproxy/stconn-t.h
src/cli.c
src/http_ana.c
src/stconn.c

index ce0876ba0f7347affad51aa6ec0335c6aa4a4499..951b790730d6ef2df596b02a94fccad2f39f3482 100644 (file)
@@ -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;
index d8c3d44abe956413bc3ca22b1f7ccfa0444d1fa4..5f859b93d840b99d3e531c29b03d02d987b40191 100644 (file)
--- 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 */
 
index 4ec3a389b9d6b94c6d04196d73ba906fbbcf7bb5..bc9865a1e07f1a069a44707d3202bbc004051809 100644 (file)
@@ -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;
index ceb429b380af9ca671f215f4ddb17978a9e7e6e9..c60afcc3936e916f04facb0118d759d5eebba754 100644 (file)
@@ -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);