mirror of
http://git.haproxy.org/git/haproxy.git
synced 2026-02-11 05:42:54 +02:00
BUG/MEDIUM: queues: Stricly respect maxconn for outgoing connections
The "served" field of struct server is used to know how many connections are currently in use for a server. But served used to be incremented way after the server was picked, so there were race conditions that could lead more than maxconn connections to be allocated for one server. To fix this, increment served way earlier, and make sure at the time that it never goes past maxconn. We now should never have more outgoing connections than set by maxconn.
This commit is contained in:
committed by
Olivier Houchard
parent
4332fed6c1
commit
3372a2ea00
28
src/queue.c
28
src/queue.c
@@ -259,6 +259,9 @@ static int pendconn_process_next_strm(struct server *srv, struct proxy *px, int
|
||||
struct pendconn *p = NULL;
|
||||
struct pendconn *pp = NULL;
|
||||
u32 pkey, ppkey;
|
||||
int served;
|
||||
int maxconn;
|
||||
int got_it = 0;
|
||||
|
||||
p = NULL;
|
||||
if (srv->queue.length)
|
||||
@@ -277,7 +280,25 @@ static int pendconn_process_next_strm(struct server *srv, struct proxy *px, int
|
||||
|
||||
if (!p && !pp)
|
||||
return 0;
|
||||
else if (!pp)
|
||||
|
||||
served = _HA_ATOMIC_LOAD(&srv->served);
|
||||
maxconn = srv_dynamic_maxconn(srv);
|
||||
|
||||
while (served < maxconn && !got_it)
|
||||
got_it = _HA_ATOMIC_CAS(&srv->served, &served, served + 1);
|
||||
|
||||
/* No more slot available, give up */
|
||||
if (!got_it) {
|
||||
if (pp)
|
||||
HA_SPIN_UNLOCK(QUEUE_LOCK, &px->queue.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we know we'll have something available.
|
||||
* Let's try to allocate a slot on the server.
|
||||
*/
|
||||
if (!pp)
|
||||
goto use_p; /* p != NULL */
|
||||
else if (!p)
|
||||
goto use_pp; /* pp != NULL */
|
||||
@@ -394,10 +415,13 @@ int process_srv_queue(struct server *s)
|
||||
|
||||
HA_SPIN_LOCK(QUEUE_LOCK, &s->queue.lock);
|
||||
while (s->served < maxconn) {
|
||||
/*
|
||||
* pendconn_process_next_strm() will increment
|
||||
* the served field, only if it is < maxconn.
|
||||
*/
|
||||
stop = !pendconn_process_next_strm(s, p, px_ok);
|
||||
if (stop)
|
||||
break;
|
||||
_HA_ATOMIC_INC(&s->served);
|
||||
done++;
|
||||
if (done >= global.tune.maxpollevents)
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user