]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: spoe: Remove idle applets and pipelining support
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 17 Jun 2024 16:17:11 +0000 (18:17 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 12 Jul 2024 13:27:04 +0000 (15:27 +0200)
Management of idle applets is removed. Consequently, the pipelining support
is also removed. It is a huge change but it should be transparent for the
agents, except regarding the performances. Of course, being able to reuse
already openned connections and being able to multiplex frames on a given
connection is a must have. These features will be restored later.

hello and idle timeout are not longer used. Because an applet is spawned to
process a NOTIFY frame and closed after receiving the ACK reply, the
processing timeout is the only one required. In addition, the parameters to
limit the SPOE applet creation are no longer used too.

The related issue is #2502.

include/haproxy/spoe-t.h
src/flt_spoe.c

index 7c4d985f9b19b28dc7516b572cc064bef2243a75..47c496749e8e36bbd8f1985bc9b117286879b217 100644 (file)
@@ -284,10 +284,7 @@ struct spoe_agent {
        char                 *var_t_process;  /* Variable to set to report the processing time of the last event/group, in the TXN scope */
        char                 *var_t_total;    /* Variable to set to report the cumulative processing time, in the TXN scope */
        unsigned int          flags;          /* SPOE_FL_* */
-       unsigned int          cps_max;        /* Maximum # of connections per second */
-       unsigned int          eps_max;        /* Maximum # of errors per second */
        unsigned int          max_frame_size; /* Maximum frame size for this agent, before any negotiation */
-       unsigned int          max_fpa;        /* Maximum # of frames handled per applet at once */
 
        struct list events[SPOE_EV_EVENTS];   /* List of SPOE messages that will be sent
                                               * for each supported events */
@@ -297,27 +294,8 @@ struct spoe_agent {
        struct list messages;                 /* list of all messages attached to this SPOE agent */
 
        char *engine_id;                      /* engine-id string */
-       /* running info */
-       struct {
-               unsigned int    frame_size;     /* current maximum frame size, only used to encode messages */
-               unsigned int    processing;
-               struct freq_ctr processing_per_sec;
-
-               struct freq_ctr conn_per_sec;   /* connections per second */
-               struct freq_ctr err_per_sec;    /* connection errors per second */
-
-               unsigned int    idles;          /* # of idle applets */
-               struct eb_root  idle_applets;   /* idle SPOE applets available to process data */
-               struct list     applets;        /* all SPOE applets for this agent */
-               struct list     sending_queue;  /* Queue of streams waiting to send data */
-               __decl_thread(HA_SPINLOCK_T lock);
-       } *rt;
 
        struct {
-               unsigned int applets;            /* # of SPOE applets */
-               unsigned int idles;              /* # of idle applets */
-               unsigned int nb_sending;         /* # of streams waiting to send data */
-               unsigned int nb_waiting;         /* # of streams waiting for a ack */
                unsigned long long nb_processed; /* # of frames processed by the SPOE */
                unsigned long long nb_errors;    /* # of errors during the processing */
        } counters;
@@ -343,7 +321,6 @@ struct spoe_context {
 
        struct buffer       buffer;       /* Buffer used to store a encoded messages */
        struct buffer_wait  buffer_wait;  /* position in the list of resources waiting for a buffer */
-       struct list         list;
 
        enum spoe_ctx_state state;        /* SPOE_CTX_ST_* */
        unsigned int        flags;        /* SPOE_CTX_FL_* */
@@ -357,14 +334,6 @@ struct spoe_context {
 
        struct {
                ullong         start_ts;    /* start date of the current event/group */
-               ullong         request_ts;  /* date the frame processing starts */
-               ullong         queue_ts;    /* date the frame is queued */
-               ullong         wait_ts;     /* date the stream starts waiting for a response */
-               ullong         response_ts; /* date the response processing starts */
-               long           t_request;   /* delay to encode and push the frame in queue */
-               long           t_queue;     /* delay before the frame gets out the sending queue */
-               long           t_waiting;   /* delay before the response is received */
-               long           t_response;  /* delay to process the response (from the stream pov) */
                long           t_process;   /* processing time of the last event/group */
                unsigned long  t_total;     /* cumulative processing time */
        } stats; /* Stats for this stream */
@@ -384,10 +353,8 @@ struct spoe_appctx {
 
        struct buffer       buffer;         /* Buffer used to store a encoded messages */
        struct buffer_wait  buffer_wait;    /* position in the list of resources waiting for a buffer */
-       struct list         waiting_queue;  /* list of streams waiting for a ACK frame, in sync and pipelining mode */
-       struct list         list;           /* next spoe appctx for the same agent */
-       struct eb32_node    node;           /* node used for applets tree */
-       unsigned int        cur_fpa;
+
+       struct spoe_context *spoe_ctx;      /* The SPOE context to handle */
 };
 
 #endif /* _HAPROXY_SPOE_T_H */
index 1a5768bd72c957003b70e335a46c3435318a11ec..bc984cd1718078a4929e4c89368653b3b30c19cf 100644 (file)
@@ -60,9 +60,6 @@
 /* SPOE filter id. Used to identify SPOE filters */
 const char *spoe_filter_id = "SPOE filter";
 
-/* Set if the handle on SIGUSR1 is registered */
-static int sighandler_registered = 0;
-
 /* The name of the SPOE engine, used during the parsing */
 char *curengine = NULL;
 
@@ -92,7 +89,6 @@ DECLARE_STATIC_POOL(pool_head_spoe_appctx, "spoe_appctx", sizeof(struct spoe_app
 
 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);
@@ -149,7 +145,6 @@ spoe_release_agent(struct spoe_agent *agent)
 {
        struct spoe_message *msg, *msgback;
        struct spoe_group   *grp, *grpback;
-       int                  i;
 
        if (!agent)
                return;
@@ -168,12 +163,6 @@ spoe_release_agent(struct spoe_agent *agent)
                spoe_release_group(grp);
        }
        free(agent->engine_id);
-       if (agent->rt) {
-               for (i = 0; i < global.nbthread; ++i) {
-                       HA_SPIN_DESTROY(&agent->rt[i].lock);
-               }
-       }
-       free(agent->rt);
        free(agent);
 }
 
@@ -464,8 +453,7 @@ spoe_prepare_hadiscon_frame(struct appctx *appctx, char *frame, size_t size)
  * encoded bytes in the frame on success, 0 if an encoding error occurred and -1
  * if a fatal error occurred. */
 static int
-spoe_prepare_hanotify_frame(struct appctx *appctx, struct spoe_context *ctx,
-                           char *frame, size_t size)
+spoe_prepare_hanotify_frame(struct appctx *appctx, char *frame, size_t size)
 {
        char        *p, *end;
        unsigned int stream_id, frame_id;
@@ -475,8 +463,8 @@ spoe_prepare_hanotify_frame(struct appctx *appctx, struct spoe_context *ctx,
        p   = frame;
        end = frame+size;
 
-       stream_id = ctx->stream_id;
-       frame_id  = ctx->frame_id;
+       stream_id = SPOE_APPCTX(appctx)->spoe_ctx->stream_id;
+       frame_id  = SPOE_APPCTX(appctx)->spoe_ctx->frame_id;
 
        /* Set Frame type */
        *p++ = SPOE_FRM_T_HAPROXY_NOTIFY;
@@ -493,10 +481,10 @@ spoe_prepare_hanotify_frame(struct appctx *appctx, struct spoe_context *ctx,
                goto too_big;
 
        /* Copy encoded messages, if possible */
-       sz = b_data(&ctx->buffer);
+       sz = b_data(&SPOE_APPCTX(appctx)->spoe_ctx->buffer);
        if (p + sz >= end)
                goto too_big;
-       memcpy(p, b_head(&ctx->buffer), sz);
+       memcpy(p, b_head(&SPOE_APPCTX(appctx)->spoe_ctx->buffer), sz);
        p += sz;
 
        return (p - frame);
@@ -790,8 +778,7 @@ spoe_handle_agentdiscon_frame(struct appctx *appctx, char *frame, size_t size)
 /* Decode ACK frame sent by an agent. It returns the number of read bytes on
  * success, 0 if the frame can be ignored and -1 if an error occurred. */
 static int
-spoe_handle_agentack_frame(struct appctx *appctx, struct spoe_context **ctx,
-                          char *frame, size_t size)
+spoe_handle_agentack_frame(struct appctx *appctx, char *frame, size_t size)
 {
        char              *p, *end;
        uint64_t           stream_id, frame_id;
@@ -800,17 +787,16 @@ spoe_handle_agentack_frame(struct appctx *appctx, struct spoe_context **ctx,
 
        p    = frame;
        end  = frame + size;
-       *ctx = NULL;
 
        /* Check frame type */
        if (*p++ != SPOE_FRM_T_AGENT_ACK) {
                SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_INVALID;
-               return 0;
+               return -1;
        }
 
        if (size < 7 /* TYPE + METADATA */) {
                SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_INVALID;
-               return 0;
+               return -1;
        }
 
        /* Retrieve flags */
@@ -827,37 +813,24 @@ spoe_handle_agentack_frame(struct appctx *appctx, struct spoe_context **ctx,
        /* Get the stream-id and the frame-id */
        if (decode_varint(&p, end, &stream_id) == -1) {
                SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_INVALID;
-               return 0;
+               return -1;
        }
        if (decode_varint(&p, end, &frame_id) == -1) {
                SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_INVALID;
-               return 0;
+               return -1;
        }
 
-       list_for_each_entry((*ctx), &SPOE_APPCTX(appctx)->waiting_queue, list) {
-               if ((*ctx)->stream_id == (unsigned int)stream_id &&
-                   (*ctx)->frame_id == (unsigned int)frame_id)
+       if (SPOE_APPCTX(appctx)->spoe_ctx->stream_id == (unsigned int)stream_id &&
+           SPOE_APPCTX(appctx)->spoe_ctx->frame_id == (unsigned int)frame_id)
                        goto found;
-       }
 
        /* No Stream found, ignore the frame */
        SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_FRAMEID_NOTFOUND;
-       if (appctx->st0 == SPOE_APPCTX_ST_WAITING_SYNC_ACK) {
-               /* Report an error if we are waiting the ack for another frame,
-                * but not if there is no longer frame waiting for a ack
-                * (timeout)
-                */
-               if (!LIST_ISEMPTY(&SPOE_APPCTX(appctx)->waiting_queue))
-                       return -1;
-               appctx->st0 = SPOE_APPCTX_ST_PROCESSING;
-               SPOE_APPCTX(appctx)->cur_fpa = 0;
-       }
-       return 0;
+       return -1;
 
   found:
        if (!spoe_acquire_buffer(&SPOE_APPCTX(appctx)->buffer,
                                 &SPOE_APPCTX(appctx)->buffer_wait)) {
-               *ctx = NULL;
                return 1; /* Retry later */
        }
 
@@ -867,12 +840,6 @@ spoe_handle_agentack_frame(struct appctx *appctx, struct spoe_context **ctx,
        b_set_data(&SPOE_APPCTX(appctx)->buffer, len);
        p += len;
 
-       /* Transfer the buffer ownership to the SPOE context */
-       (*ctx)->buffer = SPOE_APPCTX(appctx)->buffer;
-       SPOE_APPCTX(appctx)->buffer = BUF_NULL;
-
-       (*ctx)->state = SPOE_CTX_ST_DONE;
-
   end:
        return (p - frame);
 }
@@ -1063,11 +1030,6 @@ spoe_init_appctx(struct appctx *appctx)
        s->do_log = NULL;
        s->scb->flags |= SC_FL_RCV_ONCE;
 
-       HA_SPIN_LOCK(SPOE_APPLET_LOCK, &agent->rt[tid].lock);
-       LIST_APPEND(&agent->rt[tid].applets, &spoe_appctx->list);
-       HA_SPIN_UNLOCK(SPOE_APPLET_LOCK, &agent->rt[tid].lock);
-       _HA_ATOMIC_INC(&agent->counters.applets);
-
        appctx->st0 = SPOE_APPCTX_ST_CONNECT;
        task_wakeup(spoe_appctx->task, TASK_WOKEN_INIT);
        return 0;
@@ -1083,32 +1045,14 @@ static void
 spoe_release_appctx(struct appctx *appctx)
 {
        struct spoe_appctx  *spoe_appctx = SPOE_APPCTX(appctx);
-       struct spoe_agent   *agent;
-       struct spoe_context *ctx, *back;
 
        if (spoe_appctx == NULL)
                return;
 
-       appctx->svcctx = NULL;
-       agent = spoe_appctx->agent;
-
-       /* Remove applet from the list of running applets */
-       _HA_ATOMIC_DEC(&agent->counters.applets);
-       HA_SPIN_LOCK(SPOE_APPLET_LOCK, &agent->rt[tid].lock);
-       if (!LIST_ISEMPTY(&spoe_appctx->list)) {
-               LIST_DELETE(&spoe_appctx->list);
-               LIST_INIT(&spoe_appctx->list);
-       }
-       HA_SPIN_UNLOCK(SPOE_APPLET_LOCK, &agent->rt[tid].lock);
+       appctx->svcctx = NULL;
 
        /* Shutdown the server connection, if needed */
        if (appctx->st0 != SPOE_APPCTX_ST_END) {
-               if (appctx->st0 == SPOE_APPCTX_ST_IDLE) {
-                       eb32_delete(&spoe_appctx->node);
-                       _HA_ATOMIC_DEC(&agent->counters.idles);
-                       agent->rt[tid].idles--;
-               }
-
                appctx->st0 = SPOE_APPCTX_ST_END;
                if (spoe_appctx->status_code == SPOE_FRM_ERR_NONE)
                        spoe_appctx->status_code = SPOE_FRM_ERR_IO;
@@ -1117,37 +1061,12 @@ spoe_release_appctx(struct appctx *appctx)
        /* Destroy the task attached to this applet */
        task_destroy(spoe_appctx->task);
 
-       /* Report an error to all streams in the appctx waiting queue */
-       list_for_each_entry_safe(ctx, back, &spoe_appctx->waiting_queue, list) {
-               LIST_DELETE(&ctx->list);
-               LIST_INIT(&ctx->list);
-               _HA_ATOMIC_DEC(&agent->counters.nb_waiting);
-               spoe_update_stat_time(&ctx->stats.wait_ts, &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);
-       }
-
-       if (LIST_ISEMPTY(&agent->rt[tid].applets)) {
-               /* It is the last running applet and the sending queue is not empty.
-                * So try to start a new applet if HAproxy is not stopping.
-                */
-               if (!stopping && !LIST_ISEMPTY(&agent->rt[tid].sending_queue) && spoe_create_appctx(agent->spoe_conf))
-                       goto end;
-
-               /* Otherwise, report an error to all streams in the sending queue.
-                */
-               list_for_each_entry_safe(ctx, back, &agent->rt[tid].sending_queue, list) {
-                       LIST_DELETE(&ctx->list);
-                       LIST_INIT(&ctx->list);
-                       _HA_ATOMIC_DEC(&agent->counters.nb_sending);
-                       spoe_update_stat_time(&ctx->stats.queue_ts, &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);
-               }
+       if (spoe_appctx->spoe_ctx)  {
+               /* Report an error to stream */
+               spoe_appctx->spoe_ctx->spoe_appctx = NULL;
+               spoe_appctx->spoe_ctx->state = SPOE_CTX_ST_ERROR;
+               spoe_appctx->spoe_ctx->status_code = (spoe_appctx->status_code + 0x100);
+               task_wakeup(spoe_appctx->spoe_ctx->strm->task, TASK_WOKEN_MSG);
        }
 
   end:
@@ -1155,18 +1074,12 @@ spoe_release_appctx(struct appctx *appctx)
        spoe_release_buffer(&spoe_appctx->buffer,
                            &spoe_appctx->buffer_wait);
        pool_free(pool_head_spoe_appctx, spoe_appctx);
-
-       /* Update runtinme agent info */
-       agent->rt[tid].frame_size = agent->max_frame_size;
-       list_for_each_entry(spoe_appctx, &agent->rt[tid].applets, list)
-               HA_ATOMIC_UPDATE_MIN(&agent->rt[tid].frame_size, spoe_appctx->max_frame_size);
 }
 
 static int
 spoe_handle_connect_appctx(struct appctx *appctx)
 {
-       struct stconn *sc    = appctx_sc(appctx);
-       struct spoe_agent  *agent = SPOE_APPCTX(appctx)->agent;
+       struct stconn *sc = appctx_sc(appctx);
        char *frame, *buf;
        int   ret;
 
@@ -1185,10 +1098,6 @@ spoe_handle_connect_appctx(struct appctx *appctx)
                goto exit;
        }
 
-       if (SPOE_APPCTX(appctx)->task->expire == TICK_ETERNITY)
-               SPOE_APPCTX(appctx)->task->expire =
-                       tick_add_ifset(now_ms, agent->timeout.hello);
-
        /* 4 bytes are reserved at the beginning of <buf> to store the frame
         * length. */
        buf = trash.area; frame = buf+4;
@@ -1224,8 +1133,7 @@ spoe_handle_connect_appctx(struct appctx *appctx)
 static int
 spoe_handle_connecting_appctx(struct appctx *appctx)
 {
-       struct stconn *sc     = appctx_sc(appctx);
-       struct spoe_agent  *agent  = SPOE_APPCTX(appctx)->agent;
+       struct stconn *sc = appctx_sc(appctx);
        char  *frame;
        int    ret;
 
@@ -1256,14 +1164,7 @@ spoe_handle_connecting_appctx(struct appctx *appctx)
                        goto stop;
 
                default:
-                       _HA_ATOMIC_INC(&agent->counters.idles);
-                       agent->rt[tid].idles++;
                        appctx->st0 = SPOE_APPCTX_ST_IDLE;
-                       SPOE_APPCTX(appctx)->node.key = 0;
-                       eb32_insert(&agent->rt[tid].idle_applets, &SPOE_APPCTX(appctx)->node);
-
-                       /* Update runtinme agent info */
-                       HA_ATOMIC_UPDATE_MIN(&agent->rt[tid].frame_size, SPOE_APPCTX(appctx)->max_frame_size);
                        goto next;
        }
 
@@ -1272,8 +1173,6 @@ spoe_handle_connecting_appctx(struct appctx *appctx)
        if (trash.data)
                co_skip(sc_oc(sc), trash.data);
 
-       SPOE_APPCTX(appctx)->task->expire =
-               tick_add_ifset(now_ms, agent->timeout.idle);
        return 0;
   stop:
        return 1;
@@ -1284,10 +1183,8 @@ spoe_handle_connecting_appctx(struct appctx *appctx)
 
 
 static int
-spoe_handle_sending_frame_appctx(struct appctx *appctx, int *skip)
+spoe_handle_sending_frame_appctx(struct appctx *appctx)
 {
-       struct spoe_agent   *agent = SPOE_APPCTX(appctx)->agent;
-       struct spoe_context *ctx = NULL;
        char *frame, *buf;
        int   ret;
 
@@ -1295,79 +1192,44 @@ spoe_handle_sending_frame_appctx(struct appctx *appctx, int *skip)
         * length. */
        buf = trash.area; frame = buf+4;
 
-       if (LIST_ISEMPTY(&agent->rt[tid].sending_queue)) {
-               *skip = 1;
-               ret   = 1;
+       if (!SPOE_APPCTX(appctx)->spoe_ctx) {
+               appctx->st0 = SPOE_APPCTX_ST_DISCONNECT;
+               ret  = -1;
                goto end;
        }
-       else {
-               ctx = LIST_NEXT(&agent->rt[tid].sending_queue, typeof(ctx), list);
-               ret = spoe_prepare_hanotify_frame(appctx, ctx, frame,
-                                                 SPOE_APPCTX(appctx)->max_frame_size);
-
-       }
-
+       ret = spoe_prepare_hanotify_frame(appctx, frame, SPOE_APPCTX(appctx)->max_frame_size);
        if (ret > 1)
                ret = spoe_send_frame(appctx, buf, ret);
 
        switch (ret) {
                case -1: /* error */
-                       appctx->st0 = SPOE_APPCTX_ST_DISCONNECT;
-                       goto end;
-
                case 0: /* ignore */
-                       spoe_release_buffer(&ctx->buffer, &ctx->buffer_wait);
-                       LIST_DELETE(&ctx->list);
-                       LIST_INIT(&ctx->list);
-                       _HA_ATOMIC_DEC(&agent->counters.nb_sending);
-                       spoe_update_stat_time(&ctx->stats.queue_ts, &ctx->stats.t_queue);
-                       ctx->spoe_appctx = NULL;
-                       ctx->state = SPOE_CTX_ST_ERROR;
-                       ctx->status_code = (SPOE_APPCTX(appctx)->status_code + 0x100);
-                       task_wakeup(ctx->strm->task, TASK_WOKEN_MSG);
-                       *skip = 1;
+                       spoe_release_buffer(&SPOE_APPCTX(appctx)->spoe_ctx->buffer, &SPOE_APPCTX(appctx)->spoe_ctx->buffer_wait);
+                       SPOE_APPCTX(appctx)->spoe_ctx->spoe_appctx = NULL;
+                       SPOE_APPCTX(appctx)->spoe_ctx->state = SPOE_CTX_ST_ERROR;
+                       SPOE_APPCTX(appctx)->spoe_ctx->status_code = (SPOE_APPCTX(appctx)->status_code + 0x100);
+                       task_wakeup(SPOE_APPCTX(appctx)->spoe_ctx->strm->task, TASK_WOKEN_MSG);
+                       SPOE_APPCTX(appctx)->spoe_ctx = NULL;
+                       appctx->st0 = SPOE_APPCTX_ST_DISCONNECT;
                        break;
 
                case 1: /* retry */
-                       *skip = 1;
                        break;
 
                default:
-                       spoe_release_buffer(&ctx->buffer, &ctx->buffer_wait);
-                       LIST_DELETE(&ctx->list);
-                       LIST_INIT(&ctx->list);
-                       _HA_ATOMIC_DEC(&agent->counters.nb_sending);
-                       spoe_update_stat_time(&ctx->stats.queue_ts, &ctx->stats.t_queue);
-                       ctx->spoe_appctx = SPOE_APPCTX(appctx);
-                       goto frame_sent;
-       }
-       goto end;
-
-  frame_sent:
-       if (SPOE_APPCTX(appctx)->flags & SPOE_APPCTX_FL_PIPELINING) {
-               appctx->st0 = SPOE_APPCTX_ST_PROCESSING;
-               LIST_APPEND(&SPOE_APPCTX(appctx)->waiting_queue, &ctx->list);
-       }
-       else {
-               appctx->st0 = SPOE_APPCTX_ST_WAITING_SYNC_ACK;
-               *skip = 1;
-               LIST_APPEND(&SPOE_APPCTX(appctx)->waiting_queue, &ctx->list);
+                       spoe_release_buffer(&SPOE_APPCTX(appctx)->spoe_ctx->buffer, &SPOE_APPCTX(appctx)->spoe_ctx->buffer_wait);
+                       SPOE_APPCTX(appctx)->spoe_ctx->state = SPOE_CTX_ST_WAITING_ACK;
+                       appctx->st0 = SPOE_APPCTX_ST_WAITING_SYNC_ACK;
+                       break;
        }
-       _HA_ATOMIC_INC(&agent->counters.nb_waiting);
-       ctx->stats.wait_ts = now_ns;
-       SPOE_APPCTX(appctx)->cur_fpa++;
-
-       ctx->state = SPOE_CTX_ST_WAITING_ACK;
 
   end:
        return ret;
 }
 
 static int
-spoe_handle_receiving_frame_appctx(struct appctx *appctx, int *skip)
+spoe_handle_receiving_frame_appctx(struct appctx *appctx)
 {
-       struct spoe_agent   *agent = SPOE_APPCTX(appctx)->agent;
-       struct spoe_context *ctx = NULL;
        char *frame;
        int   ret;
 
@@ -1381,10 +1243,21 @@ spoe_handle_receiving_frame_appctx(struct appctx *appctx, int *skip)
                        goto end;
                }
                trash.data = ret + 4;
-               ret = spoe_handle_agentack_frame(appctx, &ctx, frame, ret);
+               if (appctx->st0 == SPOE_APPCTX_ST_WAITING_SYNC_ACK)
+                       ret = spoe_handle_agentack_frame(appctx, frame, ret);
+               else {
+                       /* ignore frame by default except if we are waiting for a ack */
+                       ret = 0;
+               }
        }
        switch (ret) {
                case -1: /* error */
+                       spoe_release_buffer(&SPOE_APPCTX(appctx)->spoe_ctx->buffer, &SPOE_APPCTX(appctx)->spoe_ctx->buffer_wait);
+                       SPOE_APPCTX(appctx)->spoe_ctx->spoe_appctx = NULL;
+                       SPOE_APPCTX(appctx)->spoe_ctx->state = SPOE_CTX_ST_ERROR;
+                       SPOE_APPCTX(appctx)->spoe_ctx->status_code = (SPOE_APPCTX(appctx)->status_code + 0x100);
+                       task_wakeup(SPOE_APPCTX(appctx)->spoe_ctx->strm->task, TASK_WOKEN_MSG);
+                       SPOE_APPCTX(appctx)->spoe_ctx = NULL;
                        appctx->st0 = SPOE_APPCTX_ST_DISCONNECT;
                        break;
 
@@ -1392,23 +1265,17 @@ spoe_handle_receiving_frame_appctx(struct appctx *appctx, int *skip)
                        break;
 
                case 1: /* retry */
-                       *skip = 1;
-                       break;
+                       goto end;
 
                default:
-                       LIST_DELETE(&ctx->list);
-                       LIST_INIT(&ctx->list);
-                       _HA_ATOMIC_DEC(&agent->counters.nb_waiting);
-                       spoe_update_stat_time(&ctx->stats.wait_ts, &ctx->stats.t_waiting);
-                       ctx->stats.response_ts = now_ns;
-                       if (ctx->spoe_appctx) {
-                               ctx->spoe_appctx->cur_fpa--;
-                               ctx->spoe_appctx = NULL;
-                       }
-                       if (appctx->st0 == SPOE_APPCTX_ST_WAITING_SYNC_ACK)
-                               appctx->st0 = SPOE_APPCTX_ST_PROCESSING;
-                       task_wakeup(ctx->strm->task, TASK_WOKEN_MSG);
-                       break;
+                       SPOE_APPCTX(appctx)->spoe_ctx->buffer = SPOE_APPCTX(appctx)->buffer;
+                       SPOE_APPCTX(appctx)->buffer = BUF_NULL;
+                       SPOE_APPCTX(appctx)->spoe_ctx->state = SPOE_CTX_ST_DONE;
+                       SPOE_APPCTX(appctx)->spoe_ctx->spoe_appctx = NULL;
+                       task_wakeup(SPOE_APPCTX(appctx)->spoe_ctx->strm->task, TASK_WOKEN_MSG);
+                       SPOE_APPCTX(appctx)->spoe_ctx = NULL;
+                       appctx->st0 = SPOE_APPCTX_ST_DISCONNECT;
+                       ret = -1;
        }
 
        /* Do not forget to remove processed frame from the output buffer */
@@ -1421,114 +1288,51 @@ spoe_handle_receiving_frame_appctx(struct appctx *appctx, int *skip)
 static int
 spoe_handle_processing_appctx(struct appctx *appctx)
 {
-       struct stconn      *sc    = appctx_sc(appctx);
-       struct server           *srv   = objt_server(__sc_strm(sc)->target);
-       struct spoe_agent       *agent = SPOE_APPCTX(appctx)->agent;
-       int ret, skip_sending = 0, skip_receiving = 0, active_s = 0, active_r = 0, close_asap = 0;
-
-       if (appctx->st1 == SPOE_APPCTX_ERR_TOUT) {
-               SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_TOUT;
-               appctx->st0 = SPOE_APPCTX_ST_DISCONNECT;
-               appctx->st1 = SPOE_APPCTX_ERR_NONE;
-               goto next;
-       }
-
-       /* Close the applet ASAP because some sessions are waiting for a free
-        * connection slot. It is only an issue in multithreaded mode.
-        */
-       close_asap = (global.nbthread > 1 &&
-                     (agent->b.be->queue.length ||
-                      (srv && (srv->queue.length || (srv->maxconn && srv->served >= srv_dynamic_maxconn(srv))))));
+       int ret;
 
        /* receiving_frame loop */
-       while (!skip_receiving) {
-               ret = spoe_handle_receiving_frame_appctx(appctx, &skip_receiving);
+       while (1) {
+               ret = spoe_handle_receiving_frame_appctx(appctx);
                switch (ret) {
                        case -1: /* error */
                                goto next;
-
                        case 0: /* ignore */
-                               active_r = 1;
                                break;
-
                        case 1: /* retry */
-                               break;
-
+                               goto send;
                        default:
-                               active_r = 1;
                                break;
                }
        }
 
-       /* Don"t try to send new frame we are waiting for at lease a ack, in
-        * sync mode or if applet must be closed ASAP
-        */
-       if (appctx->st0 == SPOE_APPCTX_ST_WAITING_SYNC_ACK || (close_asap && SPOE_APPCTX(appctx)->cur_fpa))
-               skip_sending = 1;
-
-       /* send_frame loop */
-       while (!skip_sending && SPOE_APPCTX(appctx)->cur_fpa < agent->max_fpa) {
-               ret = spoe_handle_sending_frame_appctx(appctx, &skip_sending);
-               switch (ret) {
-                       case -1: /* error */
-                               goto next;
-
-                       case 0: /* ignore */
-                               if (SPOE_APPCTX(appctx)->node.key)
-                                       SPOE_APPCTX(appctx)->node.key--;
-                               active_s++;
-                               break;
+  send:
+       if (appctx->st0 == SPOE_APPCTX_ST_WAITING_SYNC_ACK)
+               goto end;
 
-                       case 1: /* retry */
-                               break;
+       ret = spoe_handle_sending_frame_appctx(appctx);
+       switch (ret) {
+               case -1: /* error */
+                       goto next;
 
-                       default:
-                               if (SPOE_APPCTX(appctx)->node.key)
-                                       SPOE_APPCTX(appctx)->node.key--;
-                               active_s++;
-                               break;
-               }
+               case 0: /* ignore */
+                       break;
 
-               /* if applet must be close ASAP, don't send more than a frame */
-               if (close_asap)
+               case 1: /* retry */
                        break;
-       }
 
-       if (active_s || active_r) {
-               update_freq_ctr(&agent->rt[tid].processing_per_sec, active_s);
-               SPOE_APPCTX(appctx)->task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
-       }
+               default:
 
-       if (appctx->st0 == SPOE_APPCTX_ST_PROCESSING && SPOE_APPCTX(appctx)->cur_fpa < agent->max_fpa) {
-               /* If applet must be closed, don't switch it in IDLE state and
-                * close it when the last waiting frame is acknowledged.
-                */
-               if (close_asap) {
-                       if (SPOE_APPCTX(appctx)->cur_fpa)
-                               goto out;
-                       SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_NONE;
-                       appctx->st0 = SPOE_APPCTX_ST_DISCONNECT;
-                       appctx->st1 = SPOE_APPCTX_ERR_NONE;
-                       goto next;
-               }
-               _HA_ATOMIC_INC(&agent->counters.idles);
-               agent->rt[tid].idles++;
-               appctx->st0 = SPOE_APPCTX_ST_IDLE;
-               eb32_insert(&agent->rt[tid].idle_applets, &SPOE_APPCTX(appctx)->node);
+                       break;
        }
-
-  out:
+  end:
        return 1;
-
   next:
-       SPOE_APPCTX(appctx)->task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
        return 0;
 }
 
 static int
 spoe_handle_disconnect_appctx(struct appctx *appctx)
 {
-       struct spoe_agent  *agent = SPOE_APPCTX(appctx)->agent;
        char *frame, *buf;
        int   ret;
 
@@ -1557,8 +1361,6 @@ spoe_handle_disconnect_appctx(struct appctx *appctx)
        }
 
   next:
-       SPOE_APPCTX(appctx)->task->expire =
-               tick_add_ifset(now_ms, agent->timeout.idle);
        return 0;
   stop:
        return 1;
@@ -1619,7 +1421,6 @@ static void
 spoe_handle_appctx(struct appctx *appctx)
 {
        struct stconn *sc = appctx_sc(appctx);
-       struct spoe_agent  *agent;
 
        if (SPOE_APPCTX(appctx) == NULL)
                return;
@@ -1630,7 +1431,12 @@ spoe_handle_appctx(struct appctx *appctx)
        }
 
        SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_NONE;
-       agent = SPOE_APPCTX(appctx)->agent;
+       if (!SPOE_APPCTX(appctx)->spoe_ctx) {
+               if (appctx->st0 == SPOE_APPCTX_ST_CONNECT)
+                       appctx->st0 =  SPOE_APPCTX_ST_EXIT;
+               else if (appctx->st0 < SPOE_APPCTX_ST_DISCONNECT)
+                       appctx->st0 =  SPOE_APPCTX_ST_DISCONNECT;
+       }
 
   switchstate:
        switch (appctx->st0) {
@@ -1645,17 +1451,6 @@ spoe_handle_appctx(struct appctx *appctx)
                        goto switchstate;
 
                case SPOE_APPCTX_ST_IDLE:
-                       _HA_ATOMIC_DEC(&agent->counters.idles);
-                       agent->rt[tid].idles--;
-                       eb32_delete(&SPOE_APPCTX(appctx)->node);
-                       if (stopping &&
-                           LIST_ISEMPTY(&agent->rt[tid].sending_queue) &&
-                           LIST_ISEMPTY(&SPOE_APPCTX(appctx)->waiting_queue)) {
-                               SPOE_APPCTX(appctx)->task->expire =
-                                       tick_add_ifset(now_ms, agent->timeout.idle);
-                               appctx->st0 = SPOE_APPCTX_ST_DISCONNECT;
-                               goto switchstate;
-                       }
                        appctx->st0 = SPOE_APPCTX_ST_PROCESSING;
                        __fallthrough;
 
@@ -1713,18 +1508,6 @@ spoe_create_appctx(struct spoe_config *conf)
        struct spoe_appctx *spoe_appctx;
        struct appctx *appctx;
 
-       /* Do not try to create a new applet if there is no server up for the
-        * agent's backend. */
-       if (!agent->b.be->srv_act && !agent->b.be->srv_bck)
-               goto out;
-
-       /* Do not try to create a new applet if we have reached the maximum of
-        * connection per seconds */
-       if (agent->cps_max > 0) {
-               if (!freq_ctr_remain(&agent->rt[tid].conn_per_sec, agent->cps_max, 0))
-                       goto out;
-       }
-
        spoe_appctx = pool_zalloc(pool_head_spoe_appctx);
        if (spoe_appctx == NULL)
                goto out_error;
@@ -1735,9 +1518,6 @@ spoe_create_appctx(struct spoe_config *conf)
        spoe_appctx->flags           = 0;
        spoe_appctx->status_code     = SPOE_FRM_ERR_NONE;
        spoe_appctx->buffer          = BUF_NULL;
-       spoe_appctx->cur_fpa         = 0;
-       LIST_INIT(&spoe_appctx->list);
-       LIST_INIT(&spoe_appctx->waiting_queue);
 
 
        if ((appctx = appctx_new_here(&spoe_applet, NULL)) == NULL)
@@ -1747,10 +1527,6 @@ spoe_create_appctx(struct spoe_config *conf)
        if (appctx_init(appctx) == -1)
                goto out_free_appctx;
 
-       /* Increase the per-process number of cumulated connections */
-       if (agent->cps_max > 0)
-               update_freq_ctr(&agent->rt[tid].conn_per_sec, 1);
-
        appctx_wakeup(appctx);
        return appctx;
 
@@ -1766,54 +1542,6 @@ spoe_create_appctx(struct spoe_config *conf)
        return NULL;
 }
 
-static int
-spoe_queue_context(struct spoe_context *ctx)
-{
-       struct spoe_config *conf = FLT_CONF(ctx->filter);
-       struct spoe_agent  *agent = conf->agent;
-       struct spoe_appctx *spoe_appctx;
-
-       /* Check if we need to create a new SPOE applet or not. */
-       if (!LIST_ISEMPTY(&agent->rt[tid].applets) &&
-           (agent->rt[tid].processing < agent->rt[tid].idles  ||
-            agent->rt[tid].processing < read_freq_ctr(&agent->rt[tid].processing_per_sec)))
-               goto end;
-
-       spoe_create_appctx(conf);
-
-  end:
-       /* The only reason to return an error is when there is no applet */
-       if (LIST_ISEMPTY(&agent->rt[tid].applets)) {
-               ctx->status_code = SPOE_CTX_ERR_RES;
-               return -1;
-       }
-
-       /* Add the SPOE context in the sending queue if the stream has no applet
-        * already assigned and wakeup all idle applets. Otherwise, don't queue
-        * it. */
-       _HA_ATOMIC_INC(&agent->counters.nb_sending);
-       spoe_update_stat_time(&ctx->stats.request_ts, &ctx->stats.t_request);
-       ctx->stats.queue_ts = now_ns;
-       if (ctx->spoe_appctx)
-               return 1;
-       LIST_APPEND(&agent->rt[tid].sending_queue, &ctx->list);
-
-       /* Finally try to wakeup an IDLE applet. */
-       if (!eb_is_empty(&agent->rt[tid].idle_applets)) {
-               struct eb32_node *node;
-
-               node = eb32_first(&agent->rt[tid].idle_applets);
-               spoe_appctx = eb32_entry(node, struct spoe_appctx, node);
-               if (node && spoe_appctx) {
-                       eb32_delete(&spoe_appctx->node);
-                       spoe_appctx->node.key++;
-                       eb32_insert(&agent->rt[tid].idle_applets, &spoe_appctx->node);
-                       spoe_wakeup_appctx(spoe_appctx->owner);
-               }
-       }
-       return 1;
-}
-
 /***************************************************************************
  * Functions that encode SPOE messages
  **************************************************************************/
@@ -1885,7 +1613,7 @@ spoe_encode_messages(struct stream *s, struct spoe_context *ctx,
        char   *p, *end;
 
        p   = b_head(&ctx->buffer);
-       end =  p + agent->rt[tid].frame_size - FRAME_HDR_SIZE;
+       end =  p + agent->max_frame_size - FRAME_HDR_SIZE;
 
        if (type == SPOE_MSGS_BY_EVENT) { /* Loop on messages by event */
                list_for_each_entry(msg, messages, by_evt) {
@@ -2090,10 +1818,6 @@ spoe_update_stats(struct stream *s, struct spoe_agent *agent,
        if (ctx->stats.start_ts != 0) {
                spoe_update_stat_time(&ctx->stats.start_ts, &ctx->stats.t_process);
                ctx->stats.t_total    += ctx->stats.t_process;
-               ctx->stats.request_ts  = 0;
-               ctx->stats.queue_ts    = 0;
-               ctx->stats.wait_ts     = 0;
-               ctx->stats.response_ts = 0;
        }
 
        if (agent->var_t_process) {
@@ -2125,9 +1849,6 @@ static void
 spoe_handle_processing_error(struct stream *s, struct spoe_agent *agent,
                             struct spoe_context *ctx, int dir)
 {
-       if (agent->eps_max > 0)
-               update_freq_ctr(&agent->rt[tid].err_per_sec, 1);
-
        if (agent->var_on_error) {
                struct sample smp;
 
@@ -2153,13 +1874,7 @@ spoe_start_processing(struct spoe_agent *agent, struct spoe_context *ctx, int di
        if (ctx->flags & SPOE_CTX_FL_PROCESS)
                return 0;
 
-       agent->rt[tid].processing++;
        ctx->stats.start_ts   = now_ns;
-       ctx->stats.request_ts = now_ns;
-       ctx->stats.t_request  = -1;
-       ctx->stats.t_queue    = -1;
-       ctx->stats.t_waiting  = -1;
-       ctx->stats.t_response = -1;
        ctx->stats.t_process  = -1;
 
        ctx->status_code = 0;
@@ -2180,11 +1895,12 @@ spoe_stop_processing(struct spoe_agent *agent, struct spoe_context *ctx)
        if (!(ctx->flags & SPOE_CTX_FL_PROCESS))
                return;
        _HA_ATOMIC_INC(&agent->counters.nb_processed);
-       if (sa)
-               sa->cur_fpa--;
+       if (sa) {
+               sa->spoe_ctx = NULL;
+               spoe_wakeup_appctx(sa->owner);
+       }
 
        /* Reset the flag to allow next processing */
-       agent->rt[tid].processing--;
        ctx->flags &= ~SPOE_CTX_FL_PROCESS;
 
        /* Reset processing timer */
@@ -2195,16 +1911,6 @@ spoe_stop_processing(struct spoe_agent *agent, struct spoe_context *ctx)
        spoe_release_buffer(&ctx->buffer, &ctx->buffer_wait);
 
        ctx->spoe_appctx = NULL;
-
-       if (!LIST_ISEMPTY(&ctx->list)) {
-               if (ctx->state == SPOE_CTX_ST_SENDING_MSGS)
-                       _HA_ATOMIC_DEC(&agent->counters.nb_sending);
-               else
-                       _HA_ATOMIC_DEC(&agent->counters.nb_waiting);
-
-               LIST_DELETE(&ctx->list);
-               LIST_INIT(&ctx->list);
-       }
 }
 
 /* Process a list of SPOE messages. First, this functions will process messages
@@ -2229,11 +1935,6 @@ spoe_process_messages(struct stream *s, struct spoe_context *ctx,
        }
 
        if (ctx->state == SPOE_CTX_ST_READY) {
-               if (agent->eps_max > 0) {
-                       if (!freq_ctr_remain(&agent->rt[tid].err_per_sec, agent->eps_max, 0))
-                               goto skip;
-               }
-
                if (!tick_isset(ctx->process_exp)) {
                        ctx->process_exp = tick_add_ifset(now_ms, agent->timeout.processing);
                        if (dir == SMP_OPT_DIR_REQ)
@@ -2250,8 +1951,8 @@ spoe_process_messages(struct stream *s, struct spoe_context *ctx,
        }
 
        if (ctx->state == SPOE_CTX_ST_ENCODING_MSGS) {
-               if (ctx->stats.request_ts == 0)
-                       ctx->stats.request_ts = now_ns;
+               struct appctx *appctx;
+
                if (!spoe_acquire_buffer(&ctx->buffer, &ctx->buffer_wait))
                        goto out;
                ret = spoe_encode_messages(s, ctx, messages, dir, type);
@@ -2259,8 +1960,13 @@ spoe_process_messages(struct stream *s, struct spoe_context *ctx,
                        goto end;
                if (!ret)
                        goto skip;
-               if (spoe_queue_context(ctx) < 0)
+               appctx = spoe_create_appctx(conf);
+               if (!appctx) {
+                       ctx->status_code = SPOE_CTX_ERR_RES;
                        goto end;
+               }
+               ctx->spoe_appctx = SPOE_APPCTX(appctx);
+               ctx->spoe_appctx->spoe_ctx = ctx;
                ctx->state = SPOE_CTX_ST_SENDING_MSGS;
        }
 
@@ -2281,7 +1987,6 @@ spoe_process_messages(struct stream *s, struct spoe_context *ctx,
                ret = 1;
                ctx->frame_id++;
                ctx->state = SPOE_CTX_ST_READY;
-               spoe_update_stat_time(&ctx->stats.response_ts, &ctx->stats.t_response);
                goto end;
        }
 
@@ -2322,12 +2027,8 @@ spoe_process_group(struct stream *s, struct spoe_context *ctx,
        if (ret && ctx->stats.t_process != -1) {
                if (ctx->status_code || !(conf->agent_fe.options2 & PR_O2_NOLOGNORM))
                        send_log(&conf->agent_fe, (!ctx->status_code ? LOG_NOTICE : LOG_WARNING),
-                                "SPOE: [%s] <GROUP:%s> sid=%u st=%u %ld/%ld/%ld/%ld/%ld %u/%u %u/%u %llu/%llu\n",
-                                agent->id, group->id, s->uniq_id, ctx->status_code,
-                                ctx->stats.t_request, ctx->stats.t_queue, ctx->stats.t_waiting,
-                                ctx->stats.t_response, ctx->stats.t_process,
-                                agent->counters.idles, agent->counters.applets,
-                                agent->counters.nb_sending, agent->counters.nb_waiting,
+                                "SPOE: [%s] <GROUP:%s> sid=%u st=%u %ld %llu/%llu\n",
+                                agent->id, group->id, s->uniq_id, ctx->status_code, ctx->stats.t_process,
                                 agent->counters.nb_errors, agent->counters.nb_processed);
        }
        return ret;
@@ -2352,12 +2053,8 @@ spoe_process_event(struct stream *s, struct spoe_context *ctx,
        if (ret && ctx->stats.t_process != -1) {
                if (ctx->status_code || !(conf->agent_fe.options2 & PR_O2_NOLOGNORM))
                        send_log(&conf->agent_fe, (!ctx->status_code ? LOG_NOTICE : LOG_WARNING),
-                                "SPOE: [%s] <EVENT:%s> sid=%u st=%u %ld/%ld/%ld/%ld/%ld %u/%u %u/%u %llu/%llu\n",
-                                agent->id, spoe_event_str[ev], s->uniq_id, ctx->status_code,
-                                ctx->stats.t_request, ctx->stats.t_queue, ctx->stats.t_waiting,
-                                ctx->stats.t_response, ctx->stats.t_process,
-                                agent->counters.idles, agent->counters.applets,
-                                agent->counters.nb_sending, agent->counters.nb_waiting,
+                                "SPOE: [%s] <EVENT:%s> sid=%u st=%u %ld %llu/%llu\n",
+                                agent->id, spoe_event_str[ev], s->uniq_id, ctx->status_code, ctx->stats.t_process,
                                 agent->counters.nb_errors, agent->counters.nb_processed);
        }
        return ret;
@@ -2420,21 +2117,12 @@ spoe_create_context(struct stream *s, struct filter *filter)
        LIST_INIT(&ctx->buffer_wait.list);
        ctx->buffer_wait.target = ctx;
        ctx->buffer_wait.wakeup_cb = (int (*)(void *))spoe_wakeup_context;
-       LIST_INIT(&ctx->list);
 
        ctx->stream_id   = 0;
        ctx->frame_id    = 1;
        ctx->process_exp = TICK_ETERNITY;
 
        ctx->stats.start_ts   =  0;
-       ctx->stats.request_ts =  0;
-       ctx->stats.queue_ts   =  0;
-       ctx->stats.wait_ts    =  0;
-       ctx->stats.response_ts=  0;
-       ctx->stats.t_request  = -1;
-       ctx->stats.t_queue    = -1;
-       ctx->stats.t_waiting  = -1;
-       ctx->stats.t_response = -1;
        ctx->stats.t_process  = -1;
        ctx->stats.t_total    =  0;
 
@@ -2466,14 +2154,6 @@ spoe_reset_context(struct spoe_context *ctx)
        ctx->flags &= ~SPOE_CTX_FL_PROCESS;
 
        ctx->stats.start_ts   =  0;
-       ctx->stats.request_ts =  0;
-       ctx->stats.queue_ts   =  0;
-       ctx->stats.wait_ts    =  0;
-       ctx->stats.response_ts=  0;
-       ctx->stats.t_request  = -1;
-       ctx->stats.t_queue    = -1;
-       ctx->stats.t_waiting  = -1;
-       ctx->stats.t_response = -1;
        ctx->stats.t_process  = -1;
        ctx->stats.t_total    =  0;
 }
@@ -2482,48 +2162,6 @@ spoe_reset_context(struct spoe_context *ctx)
 /***************************************************************************
  * Hooks that manage the filter lifecycle (init/check/deinit)
  **************************************************************************/
-/* Signal handler: Do a soft stop, wakeup SPOE applet */
-static void
-spoe_sig_stop(struct sig_handler *sh)
-{
-       struct proxy *p;
-
-       p = proxies_list;
-       while (p) {
-               struct flt_conf *fconf;
-
-               /* SPOE filter are not initialized for disabled proxoes. Move to
-                * the next one
-                */
-               if (p->flags & PR_FL_DISABLED) {
-                       p = p->next;
-                       continue;
-               }
-
-               list_for_each_entry(fconf, &p->filter_configs, list) {
-                       struct spoe_config *conf;
-                       struct spoe_agent  *agent;
-                       struct spoe_appctx *spoe_appctx;
-                       int i;
-
-                       if (fconf->id != spoe_filter_id)
-                               continue;
-
-                       conf  = fconf->conf;
-                       agent = conf->agent;
-
-                       for (i = 0; i < global.nbthread; ++i) {
-                               HA_SPIN_LOCK(SPOE_APPLET_LOCK, &agent->rt[i].lock);
-                               list_for_each_entry(spoe_appctx, &agent->rt[i].applets, list)
-                                       spoe_wakeup_appctx(spoe_appctx->owner);
-                               HA_SPIN_UNLOCK(SPOE_APPLET_LOCK, &agent->rt[i].lock);
-                       }
-               }
-               p = p->next;
-       }
-}
-
-
 /* Initialize the SPOE filter. Returns -1 on error, else 0. */
 static int
 spoe_init(struct proxy *px, struct flt_conf *fconf)
@@ -2547,12 +2185,6 @@ spoe_init(struct proxy *px, struct flt_conf *fconf)
        if (conf->agent->engine_id == NULL)
                return -1;
 
-
-       if (!sighandler_registered) {
-               signal_register_fct(0, spoe_sig_stop, 0);
-               sighandler_registered = 1;
-       }
-
        fconf->flags |= FLT_CFG_FL_HTX;
        return 0;
 }
@@ -2581,7 +2213,6 @@ spoe_check(struct proxy *px, struct flt_conf *fconf)
        struct flt_conf    *f;
        struct spoe_config *conf = fconf->conf;
        struct proxy       *target;
-       int i;
 
        /* Check all SPOE filters for proxy <px> to be sure all SPOE agent names
         * are uniq */
@@ -2619,20 +2250,6 @@ spoe_check(struct proxy *px, struct flt_conf *fconf)
                return 1;
        }
 
-       if ((conf->agent->rt = calloc(global.nbthread, sizeof(*conf->agent->rt))) == NULL) {
-               ha_alert("Proxy %s : out of memory initializing SPOE agent '%s' declared at %s:%d.\n",
-                        px->id, conf->agent->id, conf->agent->conf.file, conf->agent->conf.line);
-               return 1;
-       }
-       for (i = 0; i < global.nbthread; ++i) {
-               conf->agent->rt[i].frame_size   = conf->agent->max_frame_size;
-               conf->agent->rt[i].processing   = 0;
-               conf->agent->rt[i].idles        = 0;
-               LIST_INIT(&conf->agent->rt[i].applets);
-               LIST_INIT(&conf->agent->rt[i].sending_queue);
-               HA_SPIN_INIT(&conf->agent->rt[i].lock);
-       }
-
        if (postresolve_logger_list(NULL, &conf->agent_fe.loggers, "SPOE agent", conf->agent->id) & ERR_CODE)
                return 1;
 
@@ -2869,8 +2486,6 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm)
                curagent->conf.file       = strdup(file);
                curagent->conf.line       = linenum;
 
-               curagent->timeout.hello      = TICK_ETERNITY;
-               curagent->timeout.idle       = TICK_ETERNITY;
                curagent->timeout.processing = TICK_ETERNITY;
 
                curagent->var_pfx        = NULL;
@@ -2878,10 +2493,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm)
                curagent->var_t_process  = NULL;
                curagent->var_t_total    = NULL;
                curagent->flags          = SPOE_FL_PIPELINING;
-               curagent->cps_max        = 0;
-               curagent->eps_max        = 0;
                curagent->max_frame_size = MAX_FRAME_SIZE;
-               curagent->max_fpa        = 20;
 
                for (i = 0; i < SPOE_EV_EVENTS; ++i)
                        LIST_INIT(&curagent->events[i]);
@@ -2961,14 +2573,18 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm)
                }
                if (alertif_too_many_args(2, file, linenum, args, &err_code))
                        goto out;
-               if (strcmp(args[1], "hello") == 0)
-                       tv = &curagent->timeout.hello;
-               else if (strcmp(args[1], "idle") == 0)
-                       tv = &curagent->timeout.idle;
+               if (strcmp(args[1], "hello") == 0) {
+                       /* TODO: Add a warning or a diag ? Ignore it for now */
+                       goto out;
+               }
+               else if (strcmp(args[1], "idle") == 0) {
+                       /* TODO: Add a warning or a diag ? Ignore it for now */
+                       goto out;
+               }
                else if (strcmp(args[1], "processing") == 0)
                        tv = &curagent->timeout.processing;
                else {
-                       ha_alert("parsing [%s:%d] : 'timeout' supports 'hello', 'idle' or 'processing' (got %s).\n",
+                       ha_alert("parsing [%s:%d] : 'timeout' supports 'processing' (got %s).\n",
                                 file, linenum, args[1]);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
@@ -3167,9 +2783,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm)
                         err_code |= ERR_ALERT | ERR_FATAL;
                         goto out;
                 }
-               if (alertif_too_many_args(1, file, linenum, args, &err_code))
-                       goto out;
-               curagent->cps_max = atol(args[1]);
+               /* TODO: Add a warning or a diag ? Ignore it for now */
        }
        else if (strcmp(args[0], "maxerrrate") == 0) {
                if (!*args[1]) {
@@ -3178,9 +2792,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm)
                         err_code |= ERR_ALERT | ERR_FATAL;
                         goto out;
                 }
-               if (alertif_too_many_args(1, file, linenum, args, &err_code))
-                       goto out;
-               curagent->eps_max = atol(args[1]);
+               /* TODO: Add a warning or a diag ? Ignore it for now */
        }
        else if (strcmp(args[0], "max-frame-size") == 0) {
                if (!*args[1]) {
@@ -3209,13 +2821,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm)
                 }
                if (alertif_too_many_args(1, file, linenum, args, &err_code))
                        goto out;
-               curagent->max_fpa = atol(args[1]);
-               if (curagent->max_fpa < 1) {
-                       ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n",
-                                file, linenum, args[0]);
-                       err_code |= ERR_ALERT | ERR_FATAL;
-                       goto out;
-               }
+               /* TODO: Add a warning or a diag ? Ignore it for now */
        }
        else if (strcmp(args[0], "register-var-names") == 0) {
                int   cur_arg;
@@ -3645,13 +3251,10 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
                          curagent->id, curagent->conf.file, curagent->conf.line);
                goto error;
        }
-       if (curagent->timeout.hello      == TICK_ETERNITY ||
-           curagent->timeout.idle       == TICK_ETERNITY ||
-           curagent->timeout.processing == TICK_ETERNITY) {
-               ha_warning("Proxy '%s': missing timeouts for SPOE agent '%s' declare at %s:%d.\n"
+       if (curagent->timeout.processing == TICK_ETERNITY) {
+               ha_warning("Proxy '%s': missing 'processing' timeout for SPOE agent '%s' declare at %s:%d.\n"
                           "   | While not properly invalid, you will certainly encounter various problems\n"
-                          "   | with such a configuration. To fix this, please ensure that all following\n"
-                          "   | timeouts are set to a non-zero value: 'hello', 'idle', 'processing'.\n",
+                          "   | with such a configuration. To fix this, please ensure it is set to a non-zero value.\n",
                           px->id, curagent->id, curagent->conf.file, curagent->conf.line);
        }
        if (curagent->var_pfx == NULL) {