From: Christopher Faulet Date: Mon, 17 Mar 2025 15:07:21 +0000 (+0100) Subject: MEDIUM: stream: Save SC and channel flags earlier in process_steam() X-Git-Tag: v3.2-dev10~44 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6365eb85e50f71f8227039a67b3e724714520a12;p=thirdparty%2Fhaproxy.git MEDIUM: stream: Save SC and channel flags earlier in process_steam() At the begining of process_stream(), the flags of the stream connectors and channels are saved to be able to handle changes performed in sub-functions (for instance in analyzers). But, some operations were performed before saving these flags: Synchronous receives and forced shutdowns. While it seems to safe for now, it is a bit annoying because some events could be missed. So, to avoid bugs in the future, the channels and stream connectors flags are now really saved before any other processing. --- diff --git a/src/stream.c b/src/stream.c index d6ebe7cad..f352f7a90 100644 --- a/src/stream.c +++ b/src/stream.c @@ -1752,11 +1752,33 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) struct stconn *scf, *scb; unsigned int rate; - DBG_TRACE_ENTER(STRM_EV_STRM_PROC, s); - activity[tid].stream_calls++; stream_cond_update_cpu_latency(s); + req = &s->req; + res = &s->res; + + scf = s->scf; + scb = s->scb; + + DBG_TRACE_ENTER(STRM_EV_STRM_PROC, s); + + /* This flag must explicitly be set every time */ + req->flags &= ~CF_WAKE_WRITE; + res->flags &= ~CF_WAKE_WRITE; + + /* Keep a copy of req/rep flags so that we can detect shutdowns */ + rqf_last = req->flags & ~CF_MASK_ANALYSER; + rpf_last = res->flags & ~CF_MASK_ANALYSER; + + /* we don't want the stream connector functions to recursively wake us up */ + scf->flags |= SC_FL_DONT_WAKE; + scb->flags |= SC_FL_DONT_WAKE; + + /* Keep a copy of SC flags */ + scf_flags = scf->flags; + scb_flags = scb->flags; + /* update pending events */ s->pending_events |= stream_map_task_state(state); s->pending_events |= HA_ATOMIC_XCHG(&s->new_events, STRM_EVT_NONE); @@ -1768,12 +1790,6 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) SF_ERR_KILLED)); } - req = &s->req; - res = &s->res; - - scf = s->scf; - scb = s->scb; - /* First, attempt to receive pending data from I/O layers */ sc_sync_recv(scf); sc_sync_recv(scb); @@ -1792,22 +1808,6 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) if (s->txn) memset(&s->txn->auth, 0, sizeof(s->txn->auth)); - /* This flag must explicitly be set every time */ - req->flags &= ~CF_WAKE_WRITE; - res->flags &= ~CF_WAKE_WRITE; - - /* Keep a copy of req/rep flags so that we can detect shutdowns */ - rqf_last = req->flags & ~CF_MASK_ANALYSER; - rpf_last = res->flags & ~CF_MASK_ANALYSER; - - /* we don't want the stream connector functions to recursively wake us up */ - scf->flags |= SC_FL_DONT_WAKE; - scb->flags |= SC_FL_DONT_WAKE; - - /* Keep a copy of SC flags */ - scf_flags = scf->flags; - scb_flags = scb->flags; - /* 1a: Check for low level timeouts if needed. We just set a flag on * stream connectors when their timeouts have expired. */