From 5354c24c7609002c4daeb58e15a6057eeae367ac Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 11 Sep 2025 09:38:41 +0200 Subject: [PATCH] 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. --- src/stconn.c | 4 ++++ src/stream.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/stconn.c b/src/stconn.c index 430f2d4e1..f9eda533f 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -1806,6 +1806,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 @@ -2311,6 +2313,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 c6e2d33f1..f7784c53a 100644 --- a/src/stream.c +++ b/src/stream.c @@ -2067,7 +2067,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)); @@ -2142,7 +2142,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));