BUG/MEDIUM: spoe: Improve error detection in SPOE applet on client abort

It is possible to interrupt a SPOE applet without reporting an error. For
instance, when the client of the parent stream aborts. Thanks to this patch,
we take care to report an error on the SPOE applet to be sure to interrupt
the processing. It is especially important if the connection to the agent is
queued. Thanks to 886a248be ("BUG/MEDIUM: mux-spop: Reject connection
attempts from a non-spop frontend"), it is no longer an issue. But there is
no reason to continue to process if the parent stream is gone.

In addition, in the SPOE filter, if the processing is interrupted when the
filter is destroyed, no specific status code was set. It is not a big deal
because it cannot be logged at this stage. But it can be used to notify the SPOE
applet. So better to set it.

This patch should be backported as far as 3.1.
This commit is contained in:
Christopher Faulet 2025-08-26 15:49:15 +02:00
parent 7a30c10587
commit 49db9739d0

View File

@ -434,6 +434,7 @@ static void spoe_release_appctx(struct appctx *appctx)
/* Shutdown the server connection, if needed */
if (appctx->st0 != SPOE_APPCTX_ST_END) {
appctx->st0 = SPOE_APPCTX_ST_END;
applet_set_error(appctx);
if (spoe_appctx->status_code == SPOP_ERR_NONE)
spoe_appctx->status_code = SPOP_ERR_IO;
}
@ -504,14 +505,15 @@ static void spoe_handle_appctx(struct appctx *appctx)
goto out;
}
if (!SPOE_APPCTX(appctx)->spoe_ctx)
appctx->st0 = SPOE_APPCTX_ST_EXIT;
switchstate:
switch (appctx->st0) {
/* case SPOE_APPCTX_ST_PROCESSING: */
case SPOE_APPCTX_ST_WAITING_ACK:
if (!spoe_handle_receiving_frame_appctx(appctx))
if (!SPOE_APPCTX(appctx)->spoe_ctx) {
appctx->st0 = SPOE_APPCTX_ST_END;
applet_set_error(appctx);
}
else if (!spoe_handle_receiving_frame_appctx(appctx))
break;
goto switchstate;
@ -1184,6 +1186,10 @@ static void spoe_destroy_context(struct filter *filter)
if (!ctx)
return;
if (ctx->state != SPOE_CTX_ST_NONE || ctx->state == SPOE_CTX_ST_READY) {
ctx->status_code = SPOE_CTX_ERR_INTERRUPT;
_HA_ATOMIC_INC(&conf->agent->counters.nb_errors);
}
spoe_stop_processing(conf->agent, ctx);
pool_free(pool_head_spoe_ctx, ctx);
filter->ctx = NULL;