spoe_handle_processing_appctx(struct appctx *appctx)
{
struct stream_interface *si = appctx->owner;
+ struct server *srv = objt_server(si_strm(si)->target);
struct spoe_agent *agent = SPOE_APPCTX(appctx)->agent;
- int ret, skip_sending = 0, skip_receiving = 0, active_s = 0, active_r = 0;
+ int ret, skip_sending = 0, skip_receiving = 0, active_s = 0, active_r = 0, close_asap = 0;
if (si->state == SI_ST_CLO || si_opposite(si)->state == SI_ST_CLO) {
SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_IO;
agent->max_fpa, spoe_appctx_state_str[appctx->st0],
SPOE_APPCTX(appctx)->node.key, SPOE_APPCTX(appctx)->flags);
- if (appctx->st0 == SPOE_APPCTX_ST_WAITING_SYNC_ACK)
+
+ /* 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))))));
+
+ /* 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;
/* receiving_frame loop */
active_s++;
break;
}
+
+ /* if applet must be close ASAP, don't send more than a frame */
+ if (close_asap)
+ break;
}
if (active_s || active_r) {
}
if (appctx->st0 == SPOE_APPCTX_ST_PROCESSING && SPOE_APPCTX(appctx)->cur_fpa < agent->max_fpa) {
- struct server *srv = objt_server(si_strm(si)->target);
-
- /* With several threads, close the applet if there are pending
- * connections or if the server is full. Otherwise, add the
- * applet in the idle list.
+ /* If applet must be closed, don't switch it in IDLE state and
+ * close it when the last waiting frame is acknowledged.
*/
- if (global.nbthread > 1 &&
- (agent->b.be->queue.length ||
- (srv && (srv->queue.length || (srv->maxconn && srv->served >=srv_dynamic_maxconn(srv)))))) {
+ 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;
appctx->st0 = SPOE_APPCTX_ST_IDLE;
eb32_insert(&agent->rt[tid].idle_applets, &SPOE_APPCTX(appctx)->node);
}
+
+ out:
return 1;
next: