MINOR: tree-wide: Test SC_FL_ERROR with SE_FL_ERROR from upper layer

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.
This commit is contained in:
Christopher Faulet 2023-04-14 11:59:15 +02:00
parent 340021b89f
commit ad46e52814
6 changed files with 34 additions and 31 deletions

View 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. */ /* 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) 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 */ ((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)))); (channel_is_empty(req) || (s->be->options & PR_O_ABRT_CLOSE))));
} }
@ -2266,9 +2266,9 @@ void back_handle_st_con(struct stream *s)
done: done:
/* retryable error ? */ /* 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 (!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; s->conn_err_type = STRM_ET_CONN_ERR;
else else
s->conn_err_type = STRM_ET_CONN_TO; 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) void back_handle_st_cer(struct stream *s)
{ {
struct stconn *sc = s->scb; 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); 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); _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) { conn && conn->err_code == CO_ER_SSL_MISMATCH_SNI) {
/* We tried to connect to a server which is configured /* We tried to connect to a server which is configured
* with "verify required" and which doesn't have the * with "verify required" and which doesn't have the
@ -2490,7 +2490,7 @@ void back_handle_st_rdy(struct stream *s)
} }
/* retryable error ? */ /* 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) if (!s->conn_err_type)
s->conn_err_type = STRM_ET_CONN_ERR; s->conn_err_type = STRM_ET_CONN_ERR;
sc->state = SC_ST_CER; sc->state = SC_ST_CER;

View File

@ -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 *fe = strm_fe(s);
struct proxy *be = s->be; 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)))) { ((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"); pcli_reply_and_close(s, "Can't connect to the target CLI!\n");
s->req.analysers &= ~AN_REQ_WAIT_CLI; s->req.analysers &= ~AN_REQ_WAIT_CLI;

View 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); 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); http_set_term_flags(s);
DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn); 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: next_one:
if (unlikely(htx_is_empty(htx) || htx->first == -1)) { if (unlikely(htx_is_empty(htx) || htx->first == -1)) {
/* 1: have we encountered a read error ? */ /* 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); 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 */ /* Always call the action function if defined */
if (rule->action_ptr) { 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) && ((s->scf->flags & SC_FL_ABRT_DONE) &&
(px->options & PR_O_ABRT_CLOSE))) (px->options & PR_O_ABRT_CLOSE)))
act_opts |= ACT_OPT_FINAL; act_opts |= ACT_OPT_FINAL;
@ -2835,7 +2835,7 @@ resume_execution:
/* Always call the action function if defined */ /* Always call the action function if defined */
if (rule->action_ptr) { 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) && ((s->scf->flags & SC_FL_ABRT_DONE) &&
(px->options & PR_O_ABRT_CLOSE))) (px->options & PR_O_ABRT_CLOSE)))
act_opts |= ACT_OPT_FINAL; act_opts |= ACT_OPT_FINAL;

View 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 * However, if SC_FL_NOLINGER is explicitly set, we know there is
* no risk so we close both sides immediately. * no risk so we close both sides immediately.
*/ */
if (!sc_ep_test(sc, SE_FL_ERROR) && !(sc->flags & SC_FL_NOLINGER) && if (!(sc->flags & (SC_FL_ERROR|SC_FL_NOLINGER|SC_FL_ABRT_DONE)) && !sc_ep_test(sc, SE_FL_ERROR) &&
!(sc->flags & SC_FL_ABRT_DONE) && !(ic->flags & CF_DONT_READ)) !(ic->flags & CF_DONT_READ))
return; return;
__fallthrough; __fallthrough;
@ -705,7 +705,7 @@ static void sc_app_shut_conn(struct stconn *sc)
* no risk so we close both sides immediately. * 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 */ /* quick close, the socket is already shut anyway */
} }
else if (sc->flags & SC_FL_NOLINGER) { 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 * However, if SC_FL_NOLINGER is explicitly set, we know there is
* no risk so we close both sides immediately. * no risk so we close both sides immediately.
*/ */
if (!sc_ep_test(sc, SE_FL_ERROR) && !(sc->flags & SC_FL_NOLINGER) && if (!(sc->flags & (SC_FL_ERROR|SC_FL_NOLINGER|SC_FL_ABRT_DONE)) && !sc_ep_test(sc, SE_FL_ERROR) &&
!(sc->flags & SC_FL_ABRT_DONE) &&
!(ic->flags & CF_DONT_READ)) !(ic->flags & CF_DONT_READ))
return; return;
@ -1095,14 +1094,14 @@ static void sc_notify(struct stconn *sc)
/* wake the task up only when needed */ /* wake the task up only when needed */
if (/* changes on the production side that must be handled: 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) * - A read event: shutdown for reads (CF_READ_EVENT + ABRT_DONE)
* end of input (CF_READ_EVENT + SC_FL_EOI) * end of input (CF_READ_EVENT + SC_FL_EOI)
* data received and no fast-forwarding (CF_READ_EVENT + !to_forward) * 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) * 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)) || ((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 */ /* changes on the consumption side */
sc_ep_test(sc, SE_FL_ERR_PENDING) || sc_ep_test(sc, SE_FL_ERR_PENDING) ||

View File

@ -907,7 +907,7 @@ static void back_establish(struct stream *s)
s->flags &= ~SF_CONN_EXP; s->flags &= ~SF_CONN_EXP;
/* errors faced after sending data need to be reported */ /* 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->req.flags |= CF_WRITE_EVENT;
s->res.flags |= CF_READ_EVENT; s->res.flags |= CF_READ_EVENT;
s->conn_err_type = STRM_ET_DATA_ERR; 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 * So let's not run a whole stream processing if only an expiration
* timeout needs to be refreshed. * 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)) && !((req->flags | res->flags) & (CF_READ_EVENT|CF_READ_TIMEOUT|CF_WRITE_EVENT|CF_WRITE_TIMEOUT)) &&
!(s->flags & SF_CONN_EXP) && !(s->flags & SF_CONN_EXP) &&
!((sc_ep_get(scf) | sc_ep_get(scb)) & SE_FL_ERROR) && !((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. * connection setup code must be able to deal with any type of abort.
*/ */
srv = objt_server(s->target); 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)) { if (sc_state_in(scf->state, SC_SB_EST|SC_SB_DIS)) {
sc_abort(scf); sc_abort(scf);
sc_shutdown(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)) { if (sc_state_in(scb->state, SC_SB_EST|SC_SB_DIS)) {
sc_abort(scb); sc_abort(scb);
sc_shutdown(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); srv = objt_server(s->target);
if (unlikely(!(s->flags & SF_ERR_MASK))) { 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 */ /* Report it if the client got an error or a read timeout expired */
req->analysers &= AN_REQ_FLT_END; 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(&s->be->be_counters.cli_aborts);
_HA_ATOMIC_INC(&sess->fe->fe_counters.cli_aborts); _HA_ATOMIC_INC(&sess->fe->fe_counters.cli_aborts);
if (sess->listener && sess->listener->counters) 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); 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 */ /* Report it if the server got an error or a read timeout expired */
res->analysers &= AN_RES_FLT_END; 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(&s->be->be_counters.srv_aborts);
_HA_ATOMIC_INC(&sess->fe->fe_counters.srv_aborts); _HA_ATOMIC_INC(&sess->fe->fe_counters.srv_aborts);
if (sess->listener && sess->listener->counters) 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 */ /* shutdown(write) pending */
if (unlikely((scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED && if (unlikely((scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED &&
channel_is_empty(req))) { 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; scb->flags |= SC_FL_NOLINGER;
sc_shutdown(scb); 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 || if (scf->state == SC_ST_DIS ||
sc_state_in(scb->state, SC_SB_RDY|SC_SB_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(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; goto resync_stconns;
/* otherwise we want to check if we need to resync the req buffer or not */ /* 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 || if (scf->state == SC_ST_DIS ||
sc_state_in(scb->state, SC_SB_RDY|SC_SB_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(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; goto resync_stconns;
if ((req->flags & ~rqf_last) & CF_MASK_ANALYSER) if ((req->flags & ~rqf_last) & CF_MASK_ANALYSER)

View 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)) { !s->be->tcp_req.inspect_delay || tick_is_expired(s->rules_exp, now_ms)) {
partial = SMP_OPT_FINAL; partial = SMP_OPT_FINAL;
/* Action may yield while the inspect_delay is not expired and there is no read error */ /* 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; act_opts |= ACT_OPT_FINAL;
} }
else 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)) { !s->be->tcp_rep.inspect_delay || tick_is_expired(s->rules_exp, now_ms)) {
partial = SMP_OPT_FINAL; partial = SMP_OPT_FINAL;
/* Action may yield while the inspect_delay is not expired and there is no read error */ /* 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; act_opts |= ACT_OPT_FINAL;
} }
else else