From fe7f615a27fc2995a492ecd77d81b1f34aa408f6 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 2 Aug 2021 17:53:56 +0200 Subject: [PATCH] BUG/MEDIUM: spoe: Create a SPOE applet if necessary when the last one is released MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit On a thread, when the last SPOE applet is released, if there are still pending streams, a new one is created. Of course, HAproxy must not be stopping. It is important to start a new applet in this case to not abort in-progress jobs, especially when a maxconn is set. Because applets may be closed to be fair with connections waiting for a free slot. This patch should partely fix the issue #1340. It depends on the commit "MINOR: spoe: Create a SPOE applet if necessary when the last one on a thread is closed". Both must be backported as far as 2.0. (cherry picked from commit 6f1296b5c70d2f513836b61cfb9a06aed2db10eb) [wt: previous patch to be picked is in fact "MINOR: spoe: Add a pointer on the filter config in the spoe_agent structure"] Signed-off-by: Willy Tarreau (cherry picked from commit 4d350af9da9a417717468d49c45d5c59ff740c80) [wt: context updates (LIST_DEL vs LISTçDELETE): reindent displaced block instead] Signed-off-by: Willy Tarreau --- src/flt_spoe.c | 51 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index e8a696f..b6c6c4e 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -102,6 +102,7 @@ struct flt_ops spoe_ops; static int spoe_queue_context(struct spoe_context *ctx); static int spoe_acquire_buffer(struct buffer *buf, struct buffer_wait *buffer_wait); static void spoe_release_buffer(struct buffer *buf, struct buffer_wait *buffer_wait); +static struct appctx *spoe_create_appctx(struct spoe_config *conf); /******************************************************************** * helper functions/globals @@ -1286,27 +1287,37 @@ spoe_release_appctx(struct appctx *appctx) } goto end; } + else { + /* It is the last running applet and the sending and waiting + * queues are not empty. Try to start a new one if HAproxy is + * not stopping. + */ + if (!stopping && + (!LIST_ISEMPTY(&agent->rt[tid].sending_queue) || !LIST_ISEMPTY(&agent->rt[tid].waiting_queue)) && + spoe_create_appctx(agent->spoe_conf)) + goto end; - /* If this was the last running applet, notify all waiting streams */ - list_for_each_entry_safe(ctx, back, &agent->rt[tid].sending_queue, list) { - LIST_DEL(&ctx->list); - LIST_INIT(&ctx->list); - _HA_ATOMIC_SUB(&agent->counters.nb_sending, 1); - spoe_update_stat_time(&ctx->stats.tv_queue, &ctx->stats.t_queue); - ctx->spoe_appctx = NULL; - ctx->state = SPOE_CTX_ST_ERROR; - ctx->status_code = (spoe_appctx->status_code + 0x100); - task_wakeup(ctx->strm->task, TASK_WOKEN_MSG); - } - list_for_each_entry_safe(ctx, back, &agent->rt[tid].waiting_queue, list) { - LIST_DEL(&ctx->list); - LIST_INIT(&ctx->list); - _HA_ATOMIC_SUB(&agent->counters.nb_waiting, 1); - spoe_update_stat_time(&ctx->stats.tv_wait, &ctx->stats.t_waiting); - ctx->spoe_appctx = NULL; - ctx->state = SPOE_CTX_ST_ERROR; - ctx->status_code = (spoe_appctx->status_code + 0x100); - task_wakeup(ctx->strm->task, TASK_WOKEN_MSG); + /* otherwise, notify all waiting streams */ + list_for_each_entry_safe(ctx, back, &agent->rt[tid].sending_queue, list) { + LIST_DEL(&ctx->list); + LIST_INIT(&ctx->list); + _HA_ATOMIC_SUB(&agent->counters.nb_sending, 1); + spoe_update_stat_time(&ctx->stats.tv_queue, &ctx->stats.t_queue); + ctx->spoe_appctx = NULL; + ctx->state = SPOE_CTX_ST_ERROR; + ctx->status_code = (spoe_appctx->status_code + 0x100); + task_wakeup(ctx->strm->task, TASK_WOKEN_MSG); + } + list_for_each_entry_safe(ctx, back, &agent->rt[tid].waiting_queue, list) { + LIST_DEL(&ctx->list); + LIST_INIT(&ctx->list); + _HA_ATOMIC_SUB(&agent->counters.nb_waiting, 1); + spoe_update_stat_time(&ctx->stats.tv_wait, &ctx->stats.t_waiting); + ctx->spoe_appctx = NULL; + ctx->state = SPOE_CTX_ST_ERROR; + ctx->status_code = (spoe_appctx->status_code + 0x100); + task_wakeup(ctx->strm->task, TASK_WOKEN_MSG); + } } end: -- 1.7.10.4