]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: spoe: stop waiting on a dead producer channel
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 4 Nov 2026 11:01:27 +0000 (12:01 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 5 Nov 2026 17:20:59 +0000 (18:20 +0100)
spoe_process_event() interrupts a pending event processing when the frontend
connector reports an error or an early close: there is no point waiting for
an agent reply if the stream is being torn down from the client side.

The check was only made on the frontend connector. With an event bound to
the response channel (on-http-response), a server error reported while the
processing is pending leaves the SPOE context in SENDING_MSGS/ WAITING_ACK
with the processing timeout armed on res->analyse_exp, and nothing can wake
it up anymore.

Test the error on the producer of the channel the event is bound to: scb
in addition to scf for response-side events, the scf checks remaining
valid whatever the direction. For the response side, only SC_FL_ERROR is
relevant: an early server close with "option abortonclose" is a
request-side semantic which is already handled on the request path. The
context then concludes with the INTERRUPT error, which lets the response
analyser proceed and deliver whatever response was already received.

This is the SPOE part of github issue #3559: with a filter engine bound to
on-http-response, an H2 backend answering early and resetting its stream
while the request body is still being uploaded used to leave the stream
spinning in process_stream() until the watchdog killed the worker. The
send-spoe-group action is covered by the http-ana fix, as it is called from
the http-response rule engine.

This patch should be backported as far as 3.2.

src/flt_spoe.c

index d9fe38635bfe94921f59ee8f1fbaefd4f13c57a0..59d2e927030a716fedf46afd5e691f15975a5095 100644 (file)
@@ -1171,7 +1171,8 @@ static int spoe_process_event(struct stream *s, struct spoe_context *ctx,
                                 agent->counters.nb_errors, agent->counters.nb_processed);
        }
        else if (ret == 0) {
-               if ((s->scf->flags & SC_FL_ERROR) ||
+               if (((dir == SMP_OPT_DIR_RES) && (s->scb->flags & SC_FL_ERROR)) ||
+                   (s->scf->flags & SC_FL_ERROR) ||
                    ((s->scf->flags & SC_FL_EOS) && proxy_abrt_close_def(s->be, 1))) {
                        ctx->status_code = SPOE_CTX_ERR_INTERRUPT;
                        spoe_stop_processing(agent, ctx);