From: Christopher Faulet Date: Fri, 23 Oct 2026 16:33:29 +0000 (+0200) Subject: BUG/MEDIUM: filters: Don't propagate a close while a filter waits on a channel X-Git-Tag: v3.5-dev10~57 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=86119aad3b44b1b5abec4990286eb298d265d560;p=haproxy.git BUG/MEDIUM: filters: Don't propagate a close while a filter waits on a channel When a filter asks to wait during the analysis of a channel, with filter.WAIT, all the data it holds are kept in the buffer, waiting to be processed when it is called back. But a close could be propagated to the other side in the meantime: when a shutdown or an abort was received on the channel, the close was forwarded to the peer side, for instance a backend EOF was immediately forwarded to the client. The stream could then terminate before the filter resumed, and the held data were lost, typically a complete response held by lua filters waiting for their wake-up, delivered with no framing and delimited by the backend close. So now, when a filter asks to wait, the close is no longer propagated: like the connection on the request side, the channel keeps the CF_AUTO_CLOSE flag cleared while a filter waits on it. The flag is restored by the analyzers on each pass, so the close is simply deferred until the filter resumes, and nothing changes for the streams without filters waiting. The "lua-eof" reg-test, introduced to record this race and marked broken until it was fixed, now passes and is un-broken. It exercises both the legacy filter chains and the filter instance mode, with a keep-alive connection reuse. This patch should be backported to all supported version after a perido of observation. --- diff --git a/reg-tests/filters/lua-eof.vtc b/reg-tests/filters/lua-eof.vtc index 751d042e0..a97f18254 100644 --- a/reg-tests/filters/lua-eof.vtc +++ b/reg-tests/filters/lua-eof.vtc @@ -1,14 +1,15 @@ varnishtest "Waiting Lua filters drain a complete response followed by backend EOF" -#REGTEST_TYPE=broken +#REGTEST_TYPE=devel feature cmd "$HAPROXY_PROGRAM -cc 'feature(LUA)'" feature ignore_unknown_macro -# A backend closing after a complete chunked response can make the stream -# close before waiting Lua callbacks resume. This also occurs with legacy -# filters before the instance refactoring. Keep the reproducer separate -# from the passing resumption test, which holds the backend open with a barrier. +# A backend closing after a complete chunked response while lua filters +# wait must not lose the held response: the close is now deferred until +# the filters resume, and the complete response is delivered to the +# client. This also exercises keep-alive reuse and both the legacy +# "filter" chains and the filter instance mode. server s1 { rxreq txresp -body "first response" diff --git a/src/filters.c b/src/filters.c index 698ddfafd..0ef8c625e 100644 --- a/src/filters.c +++ b/src/filters.c @@ -1878,6 +1878,7 @@ handle_analyzer_result(struct stream *s, struct channel *chn, wait: if (!(chn->flags & CF_ISRESP)) channel_dont_connect(chn); + channel_dont_close(chn); DBG_TRACE_DEVEL("wairing for more data", STRM_EV_FLT_ANA, s); return 0; }