From 0bbc3cf15748ff57a35c33641e185850bc01cc11 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 15 Oct 2006 14:26:02 +0200 Subject: [PATCH] [MEDIUM] fix broken redispatch option Since the connection queueing was introduced, the "redispatch" option could not cover the cases where a connection has been refused by the server after having been marked "in progress". The fix consists in doing a redispatch in the delayed connection handling code. Problem reported by Konrad Rzentarzewski. --- src/backend.c | 3 --- src/proto_http.c | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/backend.c b/src/backend.c index cda40337ce..d0c089178a 100644 --- a/src/backend.c +++ b/src/backend.c @@ -522,9 +522,6 @@ int srv_retryable_connect(struct session *t) } /* ensure that we have enough retries left */ if (srv_count_retry_down(t, conn_err)) { - /* let's try to offer this slot to anybody */ - if (may_dequeue_tasks(t->srv, t->proxy)) - task_wakeup(&rq, t->srv->queue_mgt); return 1; } } while (t->srv == NULL || t->conn_retries > 0 || !(t->proxy->options & PR_O_REDISP)); diff --git a/src/proto_http.c b/src/proto_http.c index 51a910a730..9cd75f323b 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -1454,6 +1454,30 @@ int process_srv(struct session *t) if (srv_count_retry_down(t, conn_err)) return 1; + if (t->srv && t->conn_retries == 0 && t->proxy->options & PR_O_REDISP) { + /* We're on our last chance, and the REDISP option was specified. + * We will ignore cookie and force to balance or use the dispatcher. + */ + /* let's try to offer this slot to anybody */ + if (may_dequeue_tasks(t->srv, t->proxy)) + task_wakeup(&rq, t->srv->queue_mgt); + + if (t->srv) + t->srv->failed_conns++; + t->proxy->failed_conns++; + + t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET); + t->srv = NULL; /* it's left to the dispatcher to choose a server */ + if ((t->flags & SN_CK_MASK) == SN_CK_VALID) { + t->flags &= ~SN_CK_MASK; + t->flags |= SN_CK_DOWN; + } + + /* first, get a connection */ + if (srv_redispatch_connect(t)) + return t->srv_state != SV_STIDLE; + } + do { /* Now we will try to either reconnect to the same server or * connect to another server. If the connection gets queued