From 2e56a73459b1c9e9783619c18478ba5cb4ab5843 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 26 Jan 2023 16:18:09 +0100 Subject: [PATCH] MAJOR: channel: Remove flags to report READ or WRITE errors This patch removes CF_READ_ERROR and CF_WRITE_ERROR flags. We now rely on SE_FL_ERR_PENDING and SE_FL_ERROR flags. SE_FL_ERR_PENDING is used for write errors and SE_FL_ERROR for read or unrecoverable errors. When a connection error is reported, SE_FL_ERROR and SE_FL_EOS are now set and a read event and a write event are reported to be sure the stream will properly process the error. At the stream-connector level, it is similar. When an error is reported during a send, a write event is triggered. On the read side, nothing more is performed because an error at this stage is enough to wake the stream up. A major change is brought with this patch. We stop to check flags of the ooposite channel to report abort or timeout. It also means when an read or write error is reported on a side, we no longer update the other side. Thus a read error on the server side does no long lead to a write error on the client side. This should ease errors report. --- include/haproxy/channel-t.h | 14 ++++++------- include/haproxy/sc_strm.h | 10 --------- src/backend.c | 21 ++++++++++++------- src/cli.c | 6 +++--- src/filters.c | 17 ++++++++------- src/http_ana.c | 14 ++++++------- src/stconn.c | 20 +++++++++--------- src/stream.c | 42 ++++++++----------------------------- src/tcp_rules.c | 4 ++-- 9 files changed, 60 insertions(+), 88 deletions(-) diff --git a/include/haproxy/channel-t.h b/include/haproxy/channel-t.h index 287b712ac..ef4848bc3 100644 --- a/include/haproxy/channel-t.h +++ b/include/haproxy/channel-t.h @@ -35,7 +35,7 @@ * * - pure status flags, reported by stream connector layer, which must also * be cleared before doing further I/O : - * CF_*_TIMEOUT, CF_*_ERROR + * CF_*_TIMEOUT * * - read-only indicators reported by lower data levels : * CF_STREAMER, CF_STREAMER_FAST @@ -56,7 +56,7 @@ #define CF_READ_EVENT 0x00000001 /* a read event detected on producer side */ /* unused: 0x00000002 */ #define CF_READ_TIMEOUT 0x00000004 /* timeout while waiting for producer */ -#define CF_READ_ERROR 0x00000008 /* unrecoverable error on producer side */ +/* unused 0x00000008 */ /* unused: 0x00000010 */ #define CF_SHUTR 0x00000020 /* producer has already shut down */ @@ -66,7 +66,7 @@ #define CF_WRITE_EVENT 0x00000100 /* a write event detected on consumer side */ /* unused: 0x00000200 */ #define CF_WRITE_TIMEOUT 0x00000400 /* timeout while waiting for consumer */ -#define CF_WRITE_ERROR 0x00000800 /* unrecoverable error on consumer side */ +/* unused 0x00000800 */ #define CF_WAKE_WRITE 0x00001000 /* wake the task up when there's write activity */ #define CF_SHUTW 0x00002000 /* consumer has already shut down */ @@ -120,7 +120,7 @@ #define CF_ISRESP 0x80000000 /* 0 = request channel, 1 = response channel */ /* Masks which define input events for stream analysers */ -#define CF_MASK_ANALYSER (CF_READ_EVENT|CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_EVENT|CF_WRITE_ERROR|CF_WAKE_ONCE) +#define CF_MASK_ANALYSER (CF_READ_EVENT|CF_READ_TIMEOUT|CF_WRITE_EVENT|CF_WAKE_ONCE) /* Mask for static flags which cause analysers to be woken up when they change */ #define CF_MASK_STATIC (CF_SHUTR|CF_SHUTW|CF_SHUTR_NOW|CF_SHUTW_NOW) @@ -135,15 +135,15 @@ static forceinline char *chn_show_flags(char *buf, size_t len, const char *delim /* prologue */ _(0); /* flags */ - _(CF_READ_EVENT, _(CF_READ_TIMEOUT, _(CF_READ_ERROR, + _(CF_READ_EVENT, _(CF_READ_TIMEOUT, _(CF_SHUTR, _(CF_SHUTR_NOW, _(CF_WRITE_EVENT, - _(CF_WRITE_TIMEOUT, _(CF_WRITE_ERROR, + _(CF_WRITE_TIMEOUT, _(CF_WAKE_WRITE, _(CF_SHUTW, _(CF_SHUTW_NOW, _(CF_AUTO_CLOSE, _(CF_STREAMER, _(CF_STREAMER_FAST, _(CF_WROTE_DATA, _(CF_KERN_SPLICING, _(CF_READ_DONTWAIT, _(CF_AUTO_CONNECT, _(CF_DONT_READ, _(CF_EXPECT_MORE, _(CF_SEND_DONTWAIT, _(CF_NEVER_WAIT, _(CF_WAKE_ONCE, _(CF_FLT_ANALYZE, - _(CF_EOI, _(CF_ISRESP)))))))))))))))))))))))))); + _(CF_EOI, _(CF_ISRESP)))))))))))))))))))))))); /* epilogue */ _(~0U); return buf; diff --git a/include/haproxy/sc_strm.h b/include/haproxy/sc_strm.h index 82c583a60..6e66e6c15 100644 --- a/include/haproxy/sc_strm.h +++ b/include/haproxy/sc_strm.h @@ -85,16 +85,6 @@ static inline struct stconn *sc_opposite(const struct stconn *sc) } -/* to be called only when in SC_ST_DIS with SC_FL_ERR */ -static inline void sc_report_error(struct stconn *sc) -{ - if (!__sc_strm(sc)->conn_err_type) - __sc_strm(sc)->conn_err_type = STRM_ET_DATA_ERR; - - sc_oc(sc)->flags |= CF_WRITE_ERROR; - sc_ic(sc)->flags |= CF_READ_ERROR; -} - /* sets the current and previous state of a stream connector to . This is * mainly used to create one in the established state on incoming conncetions. */ diff --git a/src/backend.c b/src/backend.c index 0e5dbfb2f..5a35bcc99 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1953,7 +1953,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 ((req->flags & (CF_READ_ERROR)) || + return (sc_ep_test(s->scf, SE_FL_ERROR) || ((req->flags & (CF_SHUTW_NOW|CF_SHUTW)) && /* empty and client aborted */ (channel_is_empty(req) || (s->be->options & PR_O_ABRT_CLOSE)))); } @@ -2022,7 +2022,8 @@ void back_try_conn_req(struct stream *s) /* Failed and not retryable. */ sc_shutr(sc); sc_shutw(sc); - req->flags |= CF_WRITE_ERROR; + sc_ep_set(sc, SE_FL_ERROR|SE_FL_EOS); + req->flags |= CF_WRITE_EVENT; s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now); @@ -2182,7 +2183,8 @@ void back_handle_st_req(struct stream *s) sc_shutr(sc); sc_shutw(sc); - s->req.flags |= CF_WRITE_ERROR; + sc_ep_set(sc, SE_FL_ERROR|SE_FL_EOS); + s->req.flags |= CF_WRITE_EVENT; s->conn_err_type = STRM_ET_CONN_RES; sc->state = SC_ST_CLO; if (s->srv_error) @@ -2208,7 +2210,8 @@ void back_handle_st_req(struct stream *s) /* we did not get any server, let's check the cause */ sc_shutr(sc); sc_shutw(sc); - s->req.flags |= CF_WRITE_ERROR; + sc_ep_set(sc, SE_FL_ERROR|SE_FL_EOS); + s->req.flags |= CF_WRITE_EVENT; if (!s->conn_err_type) s->conn_err_type = STRM_ET_CONN_OTHER; sc->state = SC_ST_CLO; @@ -2343,8 +2346,9 @@ void back_handle_st_cer(struct stream *s) /* shutw is enough to stop a connecting socket */ sc_shutw(sc); - s->req.flags |= CF_WRITE_ERROR; - s->res.flags |= CF_READ_ERROR; + sc_ep_set(sc, SE_FL_ERROR|SE_FL_EOS); + s->req.flags |= CF_WRITE_EVENT; + s->res.flags |= CF_READ_EVENT; sc->state = SC_ST_CLO; if (s->srv_error) @@ -2377,8 +2381,9 @@ void back_handle_st_cer(struct stream *s) /* shutw is enough to stop a connecting socket */ sc_shutw(sc); - s->req.flags |= CF_WRITE_ERROR; - s->res.flags |= CF_READ_ERROR; + sc_ep_set(sc, SE_FL_ERROR|SE_FL_EOS); + s->req.flags |= CF_WRITE_EVENT; + s->res.flags |= CF_READ_EVENT; sc->state = SC_ST_CLO; if (s->srv_error) diff --git a/src/cli.c b/src/cli.c index 44ca4e85c..c38efa03b 100644 --- a/src/cli.c +++ b/src/cli.c @@ -2667,7 +2667,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 ((rep->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) || + if (sc_ep_test(s->scb, SE_FL_ERR_PENDING|SE_FL_ERROR) || (rep->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) || ((rep->flags & CF_SHUTW) && (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; @@ -2783,8 +2783,8 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit) sc_set_state(s->scb, SC_ST_INI); s->scb->flags &= SC_FL_ISBACK | SC_FL_DONT_WAKE; /* we're in the context of process_stream */ - s->req.flags &= ~(CF_SHUTW|CF_SHUTW_NOW|CF_AUTO_CONNECT|CF_WRITE_ERROR|CF_STREAMER|CF_STREAMER_FAST|CF_NEVER_WAIT|CF_WROTE_DATA); - s->res.flags &= ~(CF_SHUTR|CF_SHUTR_NOW|CF_READ_ERROR|CF_STREAMER|CF_STREAMER_FAST|CF_WRITE_EVENT|CF_NEVER_WAIT|CF_WROTE_DATA|CF_READ_EVENT); + s->req.flags &= ~(CF_SHUTW|CF_SHUTW_NOW|CF_AUTO_CONNECT|CF_STREAMER|CF_STREAMER_FAST|CF_NEVER_WAIT|CF_WROTE_DATA); + s->res.flags &= ~(CF_SHUTR|CF_SHUTR_NOW|CF_STREAMER|CF_STREAMER_FAST|CF_WRITE_EVENT|CF_NEVER_WAIT|CF_WROTE_DATA|CF_READ_EVENT); s->flags &= ~(SF_DIRECT|SF_ASSIGNED|SF_BE_ASSIGNED|SF_FORCE_PRST|SF_IGNORE_PRST); s->flags &= ~(SF_CURR_SESS|SF_REDIRECTABLE|SF_SRV_REUSED); s->flags &= ~(SF_ERR_MASK|SF_FINST_MASK|SF_REDISP); diff --git a/src/filters.c b/src/filters.c index 0b98dcf5b..92aeb3a73 100644 --- a/src/filters.c +++ b/src/filters.c @@ -999,12 +999,6 @@ flt_xfer_data(struct stream *s, struct channel *chn, unsigned int an_bit) if (!HAS_DATA_FILTERS(s, chn)) goto end; - /* Be sure that the output is still opened. Else we stop the data - * filtering. */ - if ((chn->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) || - ((chn->flags & CF_SHUTW) && (chn->to_forward || co_data(chn)))) - goto end; - if (s->flags & SF_HTX) { struct htx *htx = htxbuf(&chn->buf); len = htx->data; @@ -1017,8 +1011,11 @@ flt_xfer_data(struct stream *s, struct channel *chn, unsigned int an_bit) goto end; c_adv(chn, ret); - /* Stop waiting data if the input in closed and no data is pending or if - * the output is closed. */ + /* Stop waiting data if: + * - it the output is closed + * - the input in closed and no data is pending + * - There is a READ/WRITE timeout + */ if (chn->flags & CF_SHUTW) { ret = 1; goto end; @@ -1029,6 +1026,10 @@ flt_xfer_data(struct stream *s, struct channel *chn, unsigned int an_bit) goto end; } } + if (chn->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT)) { + ret = 1; + goto end; + } /* Wait for data */ DBG_TRACE_DEVEL("waiting for more data", STRM_EV_STRM_ANA|STRM_EV_TCP_ANA|STRM_EV_FLT_ANA, s); diff --git a/src/http_ana.c b/src/http_ana.c index ba587df6d..311249123 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -785,7 +785,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, (!(req->flags & CF_READ_ERROR) ? http_error_message(s) : NULL)); + http_reply_and_close(s, txn->status, (!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); @@ -1134,8 +1134,8 @@ static __inline int do_l7_retry(struct stream *s, struct stconn *sc) req = &s->req; res = &s->res; /* Remove any write error from the request, and read error from the response */ - req->flags &= ~(CF_WRITE_ERROR | CF_WRITE_TIMEOUT | CF_SHUTW | CF_SHUTW_NOW); - res->flags &= ~(CF_READ_ERROR | CF_READ_TIMEOUT | CF_SHUTR | CF_EOI | CF_READ_EVENT | CF_SHUTR_NOW); + req->flags &= ~(CF_WRITE_TIMEOUT | CF_SHUTW | CF_SHUTW_NOW); + res->flags &= ~(CF_READ_TIMEOUT | CF_SHUTR | CF_EOI | CF_READ_EVENT | CF_SHUTR_NOW); res->analysers &= AN_RES_FLT_END; s->conn_err_type = STRM_ET_NONE; s->flags &= ~(SF_CONN_EXP | SF_ERR_MASK | SF_FINST_MASK); @@ -1216,7 +1216,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 (rep->flags & CF_READ_ERROR) { + if (sc_ep_test(s->scb, SE_FL_ERROR)) { struct connection *conn = sc_conn(s->scb); /* Perform a L7 retry because server refuses the early data. */ @@ -1342,7 +1342,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit) } /* 5: write error to client (we don't send any message then) */ - else if (rep->flags & CF_WRITE_ERROR) { + else if (sc_ep_test(s->scf, SE_FL_ERR_PENDING)) { if (txn->flags & TX_NOT_FIRST) goto abort_keep_alive; @@ -2663,7 +2663,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 ((s->req.flags & CF_READ_ERROR) || + if (sc_ep_test(s->scf, SE_FL_ERROR) || ((s->req.flags & CF_SHUTR) && (px->options & PR_O_ABRT_CLOSE))) act_opts |= ACT_OPT_FINAL; @@ -2826,7 +2826,7 @@ resume_execution: /* Always call the action function if defined */ if (rule->action_ptr) { - if ((s->req.flags & CF_READ_ERROR) || + if (sc_ep_test(s->scf, SE_FL_ERROR) || ((s->req.flags & CF_SHUTR) && (px->options & PR_O_ABRT_CLOSE))) act_opts |= ACT_OPT_FINAL; diff --git a/src/stconn.c b/src/stconn.c index 0b3147a00..46cb16392 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -846,12 +846,11 @@ static void sc_app_chk_snd_conn(struct stconn *sc) oc->wex = tick_add_ifset(now_ms, oc->wto); } - if (likely(oc->flags & (CF_WRITE_EVENT|CF_WRITE_ERROR))) { + if (likely(oc->flags & CF_WRITE_EVENT)) { struct channel *ic = sc_ic(sc); /* update timeout if we have written something */ - if ((oc->flags & (CF_SHUTW|CF_WRITE_EVENT)) == CF_WRITE_EVENT && - !channel_is_empty(oc)) + if (!(oc->flags & CF_SHUTW) && !channel_is_empty(oc)) oc->wex = tick_add_ifset(now_ms, oc->wto); if (tick_isset(ic->rex) && !(sc->flags & SC_FL_INDEP_STR)) { @@ -1133,8 +1132,8 @@ static void sc_notify(struct stconn *sc) sc_ep_clr(sc, SE_FL_WAIT_DATA); /* update OC timeouts and wake the other side up if it's waiting for room */ - if (oc->flags & (CF_WRITE_EVENT|CF_WRITE_ERROR)) { - if (!(oc->flags & CF_WRITE_ERROR) && + if (oc->flags & (CF_WRITE_EVENT)) { + if (sc_ep_test(sc, SE_FL_ERR_PENDING|SE_FL_ERROR) && !channel_is_empty(oc)) if (tick_isset(oc->wex)) oc->wex = tick_add_ifset(now_ms, oc->wto); @@ -1201,17 +1200,17 @@ 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: CF_READ_ERROR or SE_FL_ERROR + * - An error on receipt: SE_FL_ERROR * - A read event: shutdown for reads (CF_READ_EVENT + SHUTR) * end of input (CF_READ_EVENT + CF_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) && ((ic->flags & (CF_SHUTR|CF_EOI)) || !ic->to_forward || sco->state != SC_ST_EST)) || - (ic->flags & CF_READ_ERROR) || sc_ep_test(sc, SE_FL_ERROR) || + sc_ep_test(sc, SE_FL_ERROR) || /* changes on the consumption side */ - (oc->flags & CF_WRITE_ERROR) || + sc_ep_test(sc, SE_FL_ERR_PENDING) || ((oc->flags & CF_WRITE_EVENT) && ((sc->state < SC_ST_EST) || (oc->flags & CF_SHUTW) || @@ -1233,7 +1232,7 @@ static void sc_notify(struct stconn *sc) task_queue(task); } - if (ic->flags & (CF_READ_EVENT|CF_READ_ERROR)) + if (ic->flags & CF_READ_EVENT) ic->flags &= ~CF_READ_DONTWAIT; } @@ -1777,8 +1776,9 @@ 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; if (sc_ep_test(sc, SE_FL_EOS)) - sc_ep_set(sc, SE_FL_ERROR); + sc_ep_set(sc, SE_FL_ERROR); return 1; } diff --git a/src/stream.c b/src/stream.c index 382aeda49..4f964d87b 100644 --- a/src/stream.c +++ b/src/stream.c @@ -905,14 +905,8 @@ static void back_establish(struct stream *s) /* errors faced after sending data need to be reported */ if (sc_ep_test(s->scb, SE_FL_ERROR) && req->flags & CF_WROTE_DATA) { - /* Don't add CF_WRITE_ERROR if we're here because - * early data were rejected by the server, or - * http_wait_for_response() will never be called - * to send a 425. - */ - if (conn && conn->err_code != CO_ER_SSL_EARLY_FAILED) - req->flags |= CF_WRITE_ERROR; - rep->flags |= CF_READ_ERROR; + s->req.flags |= CF_WRITE_EVENT; + s->res.flags |= CF_READ_EVENT; s->conn_err_type = STRM_ET_DATA_ERR; DBG_TRACE_STATE("read/write error", STRM_EV_STRM_PROC|STRM_EV_CS_ST|STRM_EV_STRM_ERR, s); } @@ -1826,7 +1820,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) if (sc_state_in(scf->state, SC_SB_EST|SC_SB_DIS)) { sc_shutr(scf); sc_shutw(scf); - sc_report_error(scf); + //sc_report_error(scf); TODO: Be sure it is useless if (!(req->analysers) && !(res->analysers)) { _HA_ATOMIC_INC(&s->be->be_counters.cli_aborts); _HA_ATOMIC_INC(&sess->fe->fe_counters.cli_aborts); @@ -1846,7 +1840,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) if (sc_state_in(scb->state, SC_SB_EST|SC_SB_DIS)) { sc_shutr(scb); sc_shutw(scb); - sc_report_error(scb); + //sc_report_error(scb); TODO: Be sure it is useless _HA_ATOMIC_INC(&s->be->be_counters.failed_resp); if (srv) _HA_ATOMIC_INC(&srv->counters.failed_resp); @@ -2131,10 +2125,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 (req->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) { + if (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 (req->flags & CF_READ_ERROR) { + if (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) @@ -2152,15 +2146,6 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) _HA_ATOMIC_INC(&srv->counters.cli_aborts); s->flags |= SF_ERR_CLITO; } - else if (req->flags & CF_WRITE_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) - _HA_ATOMIC_INC(&sess->listener->counters->srv_aborts); - if (srv) - _HA_ATOMIC_INC(&srv->counters.srv_aborts); - s->flags |= SF_ERR_SRVCL; - } else { _HA_ATOMIC_INC(&s->be->be_counters.srv_aborts); _HA_ATOMIC_INC(&sess->fe->fe_counters.srv_aborts); @@ -2185,10 +2170,10 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) channel_erase(req); } } - else if (res->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) { + else if (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 (res->flags & CF_READ_ERROR) { + if (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) @@ -2206,15 +2191,6 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) _HA_ATOMIC_INC(&srv->counters.srv_aborts); s->flags |= SF_ERR_SRVTO; } - else if (res->flags & CF_WRITE_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) - _HA_ATOMIC_INC(&sess->listener->counters->cli_aborts); - if (srv) - _HA_ATOMIC_INC(&srv->counters.cli_aborts); - s->flags |= SF_ERR_CLICL; - } else { _HA_ATOMIC_INC(&s->be->be_counters.cli_aborts); _HA_ATOMIC_INC(&sess->fe->fe_counters.cli_aborts); @@ -2376,7 +2352,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) /* shutdown(write) pending */ if (unlikely((req->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW && channel_is_empty(req))) { - if (req->flags & CF_READ_ERROR) + if (sc_ep_test(s->scf, SE_FL_ERROR)) scb->flags |= SC_FL_NOLINGER; sc_shutw(scb); } diff --git a/src/tcp_rules.c b/src/tcp_rules.c index 15090e3d2..1d1ce7d8c 100644 --- a/src/tcp_rules.c +++ b/src/tcp_rules.c @@ -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 ((req->flags & CF_READ_ERROR) || !s->be->tcp_req.inspect_delay || tick_is_expired(s->rules_exp, now_ms)) + if (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 @@ -304,7 +304,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 ((rep->flags & CF_READ_ERROR) || !s->be->tcp_rep.inspect_delay || tick_is_expired(s->rules_exp, now_ms)) + if (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