From: Christopher Faulet Date: Thu, 11 Sep 2025 07:38:41 +0000 (+0200) Subject: BUG/MAJOR: stream: Force channel analysis on successful synchronous send X-Git-Tag: v3.0.12~19 X-Git-Url: http://git.haproxy.org/?a=commitdiff_plain;h=7a9d124c082783cf640e0f8af99ef1c85cbfe548;p=haproxy-3.0.git BUG/MAJOR: stream: Force channel analysis on successful synchronous send This patchs reverts commit a498e527b ("BUG/MAJOR: stream: Remove READ/WRITE events on channels after analysers eval") because of a regression. It was an attempt to properly detect synchronous sends, even when the stream was woken up on a write event. However, the fix was wrong because it could mask shutdowns performed during process_stream() and block the stream. Indeed, when a shutdown is performed, because an error occurred for instance, a write event is reported. The commit above could mask this event while the shutdown prevent any synchronous sends. In such case, the stream could remain blocked infinitly because an I/O event was missed. So to properly fix the original issue (#3070), the write event must not be masked before a synchronous send. Instead, we now force the channel analysis by setting explicitly CF_WAKE_ONCE flags on the corresponding channel if a write event is reported after the synchronous send. CF_WRITE_EVENT flag is remove explicitly just before, so it is quite easy to detect. This patch must be backport to all stable version in same time of the commit above. (cherry picked from commit 5354c24c7609002c4daeb58e15a6057eeae367ac) Signed-off-by: Christopher Faulet (cherry picked from commit 2e6fb599304bf85f89d501da54ecf52ade1f3fdc) Signed-off-by: Christopher Faulet (cherry picked from commit 6167935cb4d7e812b7507ba69b5ff6068da2a7bf) Signed-off-by: Christopher Faulet --- diff --git a/src/stconn.c b/src/stconn.c index d5183c7..f36cb48 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -1781,6 +1781,8 @@ void sc_conn_sync_send(struct stconn *sc) return; sc_conn_send(sc); + if (oc->flags & CF_WRITE_EVENT) + oc->flags |= CF_WAKE_ONCE; } /* Called by I/O handlers after completion.. It propagates @@ -2282,6 +2284,8 @@ void sc_applet_sync_send(struct stconn *sc) return; sc_applet_send(sc); + if (oc->flags & CF_WRITE_EVENT) + oc->flags |= CF_WAKE_ONCE; } /* Callback to be used by applet handlers upon completion. It updates the stream diff --git a/src/stream.c b/src/stream.c index ae4450a..f3f64fb 100644 --- a/src/stream.c +++ b/src/stream.c @@ -2051,7 +2051,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) rq_prod_last = scf->state; rq_cons_last = scb->state; - req->flags &= ~(CF_WAKE_ONCE|CF_READ_EVENT|CF_WRITE_EVENT); + req->flags &= ~CF_WAKE_ONCE; rqf_last = req->flags; scf_flags = (scf_flags & ~(SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) | (scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)); scb_flags = (scb_flags & ~(SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) | (scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)); @@ -2124,7 +2124,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) rp_cons_last = scf->state; rp_prod_last = scb->state; - res->flags &= ~(CF_WAKE_ONCE|CF_READ_EVENT|CF_WRITE_EVENT); + res->flags &= ~CF_WAKE_ONCE; rpf_last = res->flags; scb_flags = (scb_flags & ~(SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) | (scb->flags & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)); scf_flags = (scf_flags & ~(SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) | (scf->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED));