]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tree-wide: Test SC_FL_ERROR with SE_FL_ERROR from upper layer
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 14 Apr 2023 09:59:15 +0000 (11:59 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 14 Apr 2023 15:05:54 +0000 (17:05 +0200)
From the stream, when SE_FL_ERROR flag is tested, we now also test the
SC_FL_ERROR flag. Idea is to stop to rely on the SE descriptor to detect
errors.

src/backend.c
src/cli.c
src/http_ana.c
src/stconn.c
src/stream.c
src/tcp_rules.c

index 324ac9b63bf71071f12216f7ed8f2e1e4f753f65..9b7e9e1e24e0dbdaf177c2fe58ebd26909d1ed4d 100644 (file)
@@ -1957,7 +1957,7 @@ int srv_redispatch_connect(struct stream *s)
 /* Check if the connection request is in such a state that it can be aborted. */
 static int back_may_abort_req(struct channel *req, struct stream *s)
 {
-       return (sc_ep_test(s->scf, SE_FL_ERROR) ||
+       return ((s->scf->flags & SC_FL_ERROR) || sc_ep_test(s->scf, SE_FL_ERROR) ||
                ((s->scb->flags & (SC_FL_SHUT_WANTED|SC_FL_SHUT_DONE)) &&  /* empty and client aborted */
                 (channel_is_empty(req) || (s->be->options & PR_O_ABRT_CLOSE))));
 }
@@ -2266,9 +2266,9 @@ void back_handle_st_con(struct stream *s)
 
  done:
        /* retryable error ? */
-       if ((s->flags & SF_CONN_EXP) || sc_ep_test(sc, SE_FL_ERROR)) {
+       if ((s->flags & SF_CONN_EXP) || sc_ep_test(sc, SE_FL_ERROR) || (sc->flags & SC_FL_ERROR)) {
                if (!s->conn_err_type) {
-                       if (sc_ep_test(sc, SE_FL_ERROR))
+                       if ((sc->flags & SC_FL_ERROR) || sc_ep_test(sc, SE_FL_ERROR))
                                s->conn_err_type = STRM_ET_CONN_ERR;
                        else
                                s->conn_err_type = STRM_ET_CONN_TO;
@@ -2294,7 +2294,7 @@ void back_handle_st_con(struct stream *s)
 void back_handle_st_cer(struct stream *s)
 {
        struct stconn *sc = s->scb;
-       int must_tar = sc_ep_test(sc, SE_FL_ERROR);
+       int must_tar = !!(sc->flags & SC_FL_ERROR) || sc_ep_test(sc, SE_FL_ERROR);
 
        DBG_TRACE_ENTER(STRM_EV_STRM_PROC|STRM_EV_CS_ST, s);
 
@@ -2312,7 +2312,7 @@ void back_handle_st_cer(struct stream *s)
                        _HA_ATOMIC_DEC(&__objt_server(s->target)->cur_sess);
                }
 
-               if (sc_ep_test(sc, SE_FL_ERROR) &&
+               if (((sc->flags & SC_FL_ERROR) || sc_ep_test(sc, SE_FL_ERROR)) &&
                    conn && conn->err_code == CO_ER_SSL_MISMATCH_SNI) {
                        /* We tried to connect to a server which is configured
                         * with "verify required" and which doesn't have the
@@ -2490,7 +2490,7 @@ void back_handle_st_rdy(struct stream *s)
                }
 
                /* retryable error ? */
-               if (sc_ep_test(sc, SE_FL_ERROR)) {
+               if (sc->flags & SC_FL_ERROR || sc_ep_test(sc, SE_FL_ERROR)) {
                        if (!s->conn_err_type)
                                s->conn_err_type = STRM_ET_CONN_ERR;
                        sc->state = SC_ST_CER;
index 5f859b93d840b99d3e531c29b03d02d987b40191..14b92a502d6343e5ce2663c0d25558b4a23f8a3e 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -2715,7 +2715,7 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
        struct proxy *fe = strm_fe(s);
        struct proxy *be = s->be;
 
-       if (sc_ep_test(s->scb, SE_FL_ERROR) || (rep->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) ||
+       if ((s->scb->flags & SC_FL_ERROR) || sc_ep_test(s->scb, SE_FL_ERROR) || (rep->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) ||
            ((s->scf->flags & SC_FL_SHUT_DONE) && (rep->to_forward || co_data(rep)))) {
                pcli_reply_and_close(s, "Can't connect to the target CLI!\n");
                s->req.analysers &= ~AN_REQ_WAIT_CLI;
index bc9865a1e07f1a069a44707d3202bbc004051809..087cfe1b03e2d71afedf4cf3d278b83030999f53 100644 (file)
@@ -784,7 +784,7 @@ int http_process_tarpit(struct stream *s, struct channel *req, int an_bit)
         */
        s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
 
-       http_reply_and_close(s, txn->status, (!sc_ep_test(s->scf, SE_FL_ERROR) ? http_error_message(s) : NULL));
+       http_reply_and_close(s, txn->status, (!(s->scf->flags & SC_FL_ERROR) && !sc_ep_test(s->scf, SE_FL_ERROR) ? http_error_message(s) : NULL));
        http_set_term_flags(s);
 
        DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
@@ -1215,7 +1215,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
   next_one:
        if (unlikely(htx_is_empty(htx) || htx->first == -1)) {
                /* 1: have we encountered a read error ? */
-               if (sc_ep_test(s->scb, SE_FL_ERROR)) {
+               if ((s->scb->flags & SC_FL_ERROR) || sc_ep_test(s->scb, SE_FL_ERROR)) {
                        struct connection *conn = sc_conn(s->scb);
 
 
@@ -2672,7 +2672,7 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
 
                /* Always call the action function if defined */
                if (rule->action_ptr) {
-                       if (sc_ep_test(s->scf, SE_FL_ERROR) ||
+                       if ((s->scf->flags & SC_FL_ERROR) || sc_ep_test(s->scf, SE_FL_ERROR) ||
                            ((s->scf->flags & SC_FL_ABRT_DONE) &&
                             (px->options & PR_O_ABRT_CLOSE)))
                                act_opts |= ACT_OPT_FINAL;
@@ -2835,7 +2835,7 @@ resume_execution:
 
                /* Always call the action function if defined */
                if (rule->action_ptr) {
-                       if (sc_ep_test(s->scf, SE_FL_ERROR) ||
+                       if ((s->scf->flags & SC_FL_ERROR) || sc_ep_test(s->scf, SE_FL_ERROR) ||
                            ((s->scf->flags & SC_FL_ABRT_DONE) &&
                             (px->options & PR_O_ABRT_CLOSE)))
                                act_opts |= ACT_OPT_FINAL;
index c60afcc3936e916f04facb0118d759d5eebba754..6b2397c5f254dcd4d17296d55dd0f348a53839c4 100644 (file)
@@ -579,8 +579,8 @@ static void sc_app_shut(struct stconn *sc)
                 * However, if SC_FL_NOLINGER is explicitly set, we know there is
                 * no risk so we close both sides immediately.
                 */
-               if (!sc_ep_test(sc, SE_FL_ERROR) && !(sc->flags & SC_FL_NOLINGER) &&
-                   !(sc->flags & SC_FL_ABRT_DONE) && !(ic->flags & CF_DONT_READ))
+               if (!(sc->flags & (SC_FL_ERROR|SC_FL_NOLINGER|SC_FL_ABRT_DONE)) && !sc_ep_test(sc, SE_FL_ERROR) &&
+                   !(ic->flags & CF_DONT_READ))
                        return;
 
                __fallthrough;
@@ -705,7 +705,7 @@ static void sc_app_shut_conn(struct stconn *sc)
                 * no risk so we close both sides immediately.
                 */
 
-               if (sc_ep_test(sc, SE_FL_ERROR)) {
+               if ((sc->flags & SC_FL_ERROR) || sc_ep_test(sc, SE_FL_ERROR)) {
                        /* quick close, the socket is already shut anyway */
                }
                else if (sc->flags & SC_FL_NOLINGER) {
@@ -903,8 +903,7 @@ static void sc_app_shut_applet(struct stconn *sc)
                 * However, if SC_FL_NOLINGER is explicitly set, we know there is
                 * no risk so we close both sides immediately.
                 */
-               if (!sc_ep_test(sc, SE_FL_ERROR) && !(sc->flags & SC_FL_NOLINGER) &&
-                   !(sc->flags & SC_FL_ABRT_DONE) &&
+               if (!(sc->flags & (SC_FL_ERROR|SC_FL_NOLINGER|SC_FL_ABRT_DONE)) && !sc_ep_test(sc, SE_FL_ERROR) &&
                    !(ic->flags & CF_DONT_READ))
                        return;
 
@@ -1095,14 +1094,14 @@ static void sc_notify(struct stconn *sc)
 
        /* wake the task up only when needed */
        if (/* changes on the production side that must be handled:
-            *  - An error on receipt: SE_FL_ERROR
+            *  - An error on receipt: SC_FL_ERROR
             *  - A read event: shutdown for reads (CF_READ_EVENT + ABRT_DONE)
             *                  end of input (CF_READ_EVENT + SC_FL_EOI)
             *                  data received and no fast-forwarding (CF_READ_EVENT + !to_forward)
             *                  read event while consumer side is not established (CF_READ_EVENT + sco->state != SC_ST_EST)
             */
                ((ic->flags & CF_READ_EVENT) && ((sc->flags & SC_FL_EOI) || (sc->flags & SC_FL_ABRT_DONE) || !ic->to_forward || sco->state != SC_ST_EST)) ||
-           sc_ep_test(sc, SE_FL_ERROR) ||
+               (sc->flags & SC_FL_ERROR) || sc_ep_test(sc, SE_FL_ERROR) ||
 
            /* changes on the consumption side */
            sc_ep_test(sc, SE_FL_ERR_PENDING) ||
index 33a5a764a81bf5d1613ff55af7c95ff67c9582a1..36af89f37e5f6405dfdce11d6d7d3faa3130c4df 100644 (file)
@@ -907,7 +907,7 @@ static void back_establish(struct stream *s)
        s->flags &= ~SF_CONN_EXP;
 
        /* errors faced after sending data need to be reported */
-       if (sc_ep_test(s->scb, SE_FL_ERROR) && req->flags & CF_WROTE_DATA) {
+       if (((s->scb->flags & SC_FL_ERROR) || sc_ep_test(s->scb, SE_FL_ERROR)) && req->flags & CF_WROTE_DATA) {
                s->req.flags |= CF_WRITE_EVENT;
                s->res.flags |= CF_READ_EVENT;
                s->conn_err_type = STRM_ET_DATA_ERR;
@@ -1783,7 +1783,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
                 * So let's not run a whole stream processing if only an expiration
                 * timeout needs to be refreshed.
                 */
-               if (!((scf->flags | scb->flags) & (SC_FL_ABRT_DONE|SC_FL_SHUT_DONE)) &&
+               if (!((scf->flags | scb->flags) & (SC_FL_ERROR|SC_FL_ABRT_DONE|SC_FL_SHUT_DONE)) &&
                    !((req->flags | res->flags) & (CF_READ_EVENT|CF_READ_TIMEOUT|CF_WRITE_EVENT|CF_WRITE_TIMEOUT)) &&
                    !(s->flags & SF_CONN_EXP) &&
                    !((sc_ep_get(scf) | sc_ep_get(scb)) & SE_FL_ERROR) &&
@@ -1826,7 +1826,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
         * connection setup code must be able to deal with any type of abort.
         */
        srv = objt_server(s->target);
-       if (unlikely(sc_ep_test(scf, SE_FL_ERROR))) {
+       if (unlikely((scf->flags & SC_FL_ERROR) || sc_ep_test(scf, SE_FL_ERROR))) {
                if (sc_state_in(scf->state, SC_SB_EST|SC_SB_DIS)) {
                        sc_abort(scf);
                        sc_shutdown(scf);
@@ -1846,7 +1846,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
                }
        }
 
-       if (unlikely(sc_ep_test(scb, SE_FL_ERROR))) {
+       if (unlikely((scb->flags & SC_FL_ERROR) || sc_ep_test(scb, SE_FL_ERROR))) {
                if (sc_state_in(scb->state, SC_SB_EST|SC_SB_DIS)) {
                        sc_abort(scb);
                        sc_shutdown(scb);
@@ -2143,10 +2143,10 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
         */
        srv = objt_server(s->target);
        if (unlikely(!(s->flags & SF_ERR_MASK))) {
-               if (sc_ep_test(s->scf, SE_FL_ERROR) || req->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) {
+               if ((scf->flags & SC_FL_ERROR) || sc_ep_test(s->scf, SE_FL_ERROR) || req->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) {
                        /* Report it if the client got an error or a read timeout expired */
                        req->analysers &= AN_REQ_FLT_END;
-                       if (sc_ep_test(s->scf, SE_FL_ERROR)) {
+                       if ((scf->flags & SC_FL_ERROR) || sc_ep_test(s->scf, SE_FL_ERROR)) {
                                _HA_ATOMIC_INC(&s->be->be_counters.cli_aborts);
                                _HA_ATOMIC_INC(&sess->fe->fe_counters.cli_aborts);
                                if (sess->listener && sess->listener->counters)
@@ -2188,10 +2188,10 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
                                        channel_erase(req);
                        }
                }
-               else if (sc_ep_test(s->scb, SE_FL_ERROR) || res->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) {
+               else if ((scb->flags & SC_FL_ERROR) || sc_ep_test(s->scb, SE_FL_ERROR) || res->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) {
                        /* Report it if the server got an error or a read timeout expired */
                        res->analysers &= AN_RES_FLT_END;
-                       if (sc_ep_test(s->scb, SE_FL_ERROR)) {
+                       if ((scb->flags & SC_FL_ERROR) || sc_ep_test(s->scb, SE_FL_ERROR)) {
                                _HA_ATOMIC_INC(&s->be->be_counters.srv_aborts);
                                _HA_ATOMIC_INC(&sess->fe->fe_counters.srv_aborts);
                                if (sess->listener && sess->listener->counters)
@@ -2375,7 +2375,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
        /* shutdown(write) pending */
        if (unlikely((scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED &&
                     channel_is_empty(req))) {
-               if (sc_ep_test(s->scf, SE_FL_ERROR))
+               if ((scf->flags & SC_FL_ERROR) || sc_ep_test(s->scf, SE_FL_ERROR))
                        scb->flags |= SC_FL_NOLINGER;
                sc_shutdown(scb);
        }
@@ -2396,7 +2396,9 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
        if (scf->state == SC_ST_DIS ||
            sc_state_in(scb->state, SC_SB_RDY|SC_SB_DIS) ||
            (sc_ep_test(scf, SE_FL_ERROR) && scf->state != SC_ST_CLO) ||
-           (sc_ep_test(scb, SE_FL_ERROR) && scb->state != SC_ST_CLO))
+           (sc_ep_test(scb, SE_FL_ERROR) && scb->state != SC_ST_CLO) ||
+           ((scf->flags & SC_FL_ERROR) && scf->state != SC_ST_CLO) ||
+           ((scb->flags & SC_FL_ERROR) && scb->state != SC_ST_CLO))
                goto resync_stconns;
 
        /* otherwise we want to check if we need to resync the req buffer or not */
@@ -2515,7 +2517,9 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
        if (scf->state == SC_ST_DIS ||
            sc_state_in(scb->state, SC_SB_RDY|SC_SB_DIS) ||
            (sc_ep_test(scf, SE_FL_ERROR) && scf->state != SC_ST_CLO) ||
-           (sc_ep_test(scb, SE_FL_ERROR) && scb->state != SC_ST_CLO))
+           (sc_ep_test(scb, SE_FL_ERROR) && scb->state != SC_ST_CLO) ||
+           ((scf->flags & SC_FL_ERROR) && scf->state != SC_ST_CLO) ||
+           ((scb->flags & SC_FL_ERROR) && scb->state != SC_ST_CLO))
                goto resync_stconns;
 
        if ((req->flags & ~rqf_last) & CF_MASK_ANALYSER)
index d6ba9fbc1dfd1b30b1109ffb694bd098180b1a8b..991c16d041b20ed8bb8ec19e7c3a25350acc81d7 100644 (file)
@@ -121,7 +121,7 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit)
            !s->be->tcp_req.inspect_delay || tick_is_expired(s->rules_exp, now_ms)) {
                partial = SMP_OPT_FINAL;
                /* Action may yield while the inspect_delay is not expired and there is no read error */
-               if (sc_ep_test(s->scf, SE_FL_ERROR) || !s->be->tcp_req.inspect_delay || tick_is_expired(s->rules_exp, now_ms))
+               if ((s->scf->flags & SC_FL_ERROR) || sc_ep_test(s->scf, SE_FL_ERROR) || !s->be->tcp_req.inspect_delay || tick_is_expired(s->rules_exp, now_ms))
                        act_opts |= ACT_OPT_FINAL;
        }
        else
@@ -303,7 +303,7 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
            !s->be->tcp_rep.inspect_delay || tick_is_expired(s->rules_exp, now_ms)) {
                partial = SMP_OPT_FINAL;
                /* Action may yield while the inspect_delay is not expired and there is no read error */
-               if (sc_ep_test(s->scb, SE_FL_ERROR) || !s->be->tcp_rep.inspect_delay || tick_is_expired(s->rules_exp, now_ms))
+               if ((s->scb->flags & SC_FL_ERROR) || sc_ep_test(s->scb, SE_FL_ERROR) || !s->be->tcp_rep.inspect_delay || tick_is_expired(s->rules_exp, now_ms))
                        act_opts |= ACT_OPT_FINAL;
        }
        else