]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: zero-weight servers must not dequeue requests from the backend
authorWilly Tarreau <w@1wt.eu>
Fri, 20 Jan 2012 14:57:05 +0000 (15:57 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 20 Jan 2012 15:18:53 +0000 (16:18 +0100)
It was reported that a server configured with a zero weight would
sometimes still take connections from the backend queue. This issue is
real, it happens this way :
  1) the disabled server accepts a request with a cookie
  2) many cookie-less requests accumulate in the backend queue
  3) when the disabled server completes its request, it checks its own
     queue and the backend's queue
  4) the server takes a pending request from the backend queue and
     processes it. In response, the server's cookie is assigned to
     the client, which ensures that some requests will continue to
     be served by this server, leading back to point 1 above.

The fix consists in preventing a zero-weight server from dequeuing pending
requests from the backend. Making use of srv_is_usable() in such tests makes
the tests more robust against future changes.

This fix must be backported to 1.4 and 1.3.

include/proto/queue.h
src/queue.c

index 77964feb3783167ae01f5b1f1dfb41997ce8f4b1..7bf81370771fe5ba2e3a4b9a1a36707a93b61526 100644 (file)
@@ -1,23 +1,23 @@
 /*
-  include/proto/queue.h
-  This file defines everything related to queues.
-
 Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu
-  
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation, version 2.1
-  exclusively.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
* include/proto/queue.h
* This file defines everything related to queues.
+ *
* Copyright (C) 2000-2012 Willy Tarreau - w@1wt.eu
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, version 2.1
* exclusively.
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
 
 #ifndef _PROTO_QUEUE_H
 #define _PROTO_QUEUE_H
@@ -32,6 +32,8 @@
 #include <types/server.h>
 #include <types/task.h>
 
+#include <proto/backend.h>
+
 extern struct pool_head *pool2_pendconn;
 
 int init_pendconn();
@@ -68,7 +70,7 @@ static inline struct pendconn *pendconn_from_px(const struct proxy *px) {
  * for and if/else usage.
  */
 static inline int may_dequeue_tasks(const struct server *s, const struct proxy *p) {
-       return (s && (s->nbpend || (p->nbpend && (s->state & SRV_RUNNING))) &&
+       return (s && (s->nbpend || (p->nbpend && srv_is_usable(s->state, s->eweight))) &&
                (!s->maxconn || s->cur_sess < srv_dynamic_maxconn(s)));
 }
 
index 395d7522b1146c7ed59aafb2e42af103898d3d9c..dd6e96218b81a6f5c6b3d4403094eb9d06a4f4a1 100644 (file)
@@ -109,7 +109,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 <ps> */
-       if (!pp || !(rsrv->state & SRV_RUNNING) || (rsrv->state & (SRV_GOINGDOWN|SRV_MAINTAIN))) {
+       if (!pp || !srv_is_usable(rsrv->state, rsrv->eweight)) {
                if (!ps)
                        return NULL;
        } else {