diff --git a/include/proto/queue.h b/include/proto/queue.h index be78b53561..77964feb37 100644 --- a/include/proto/queue.h +++ b/include/proto/queue.h @@ -64,11 +64,11 @@ static inline struct pendconn *pendconn_from_px(const struct proxy *px) { } /* returns 0 if nothing has to be done for server regarding queued connections, - * and non-zero otherwise. If the server is down, we always return zero. Suited for - * and if/else usage. + * and non-zero otherwise. If the server is down, we only check its own queue. Suited + * for and if/else usage. */ static inline int may_dequeue_tasks(const struct server *s, const struct proxy *p) { - return (s && (s->state & SRV_RUNNING) && (s->nbpend || p->nbpend) && + return (s && (s->nbpend || (p->nbpend && (s->state & SRV_RUNNING))) && (!s->maxconn || s->cur_sess < srv_dynamic_maxconn(s))); } diff --git a/src/queue.c b/src/queue.c index 905994abba..c5ea0bb21a 100644 --- a/src/queue.c +++ b/src/queue.c @@ -89,6 +89,10 @@ void process_srv_queue(struct server *s) * returned. Note that neither nor may be NULL. * Priority is given to the oldest request in the queue if both and * have pending requests. This ensures that no request will be left unserved. + * The queue is not considered if the server is not RUNNING. The + * queue is still considered in this case, because if some connections remain + * there, it means that some requests have been forced there after it was seen + * down (eg: due to option persist). * The session is immediately marked as "assigned", and both its and * are set to , */ @@ -100,7 +104,7 @@ struct session *pendconn_get_next_sess(struct server *srv, struct proxy *px) ps = pendconn_from_srv(srv); pp = pendconn_from_px(px); /* we want to get the definitive pendconn in */ - if (!pp) { + if (!pp || !(srv->state & SRV_RUNNING)) { if (!ps) return NULL; } else { diff --git a/src/session.c b/src/session.c index e3a736d2bc..0d6ad8db7f 100644 --- a/src/session.c +++ b/src/session.c @@ -41,8 +41,9 @@ void session_free(struct session *s) if (s->pend_pos) pendconn_free(s->pend_pos); - if (s->srv) /* there may be requests left pending in queue */ + if (s->srv && may_dequeue_tasks(s->srv, s->be)) /* there may be requests left pending in queue */ process_srv_queue(s->srv); + if (unlikely(s->srv_conn)) { /* the session still has a reserved slot on a server, but * it should normally be only the same as the one above,