Revert "MEDIUM: queue: determine in process_srv_queue() if the proxy is usable"

This reverts commit de814dd4228fa5e528d9ac1f0e1c4c7325ee52d3.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
This commit is contained in:
Willy Tarreau 2021-06-24 07:22:08 +02:00
parent 5343d8ed6f
commit ddac4a1f35

View File

@ -253,28 +253,34 @@ static struct pendconn *pendconn_first(struct eb_root *pendconns)
* immediately marked as "assigned", and both its <srv> and <srv_conn> are set
* to <srv>.
*
* The proxy's queue will be consulted only if px_ok is non-zero.
*
* This function must only be called if the server queue _AND_ the proxy queue
* are locked (if pk_ok is set). Today it is only called by process_srv_queue.
* are locked. Today it is only called by process_srv_queue.
*
* The function returns the dequeued pendconn on success or NULL if none is
* available. It's up to the caller to add the corresponding stream to the
* server's list, to update the LB algo, update ->served, and to wake up the
* stream's task.
*/
static struct pendconn *pendconn_process_next_strm(struct server *srv, struct proxy *px, int px_ok)
static struct pendconn *pendconn_process_next_strm(struct server *srv, struct proxy *px)
{
struct pendconn *p = NULL;
struct pendconn *pp = NULL;
struct server *rsrv;
u32 pkey, ppkey;
rsrv = srv->track;
if (!rsrv)
rsrv = srv;
p = NULL;
if (srv->queue.length)
p = pendconn_first(&srv->queue.head);
pp = NULL;
if (px_ok && px->queue.length)
if (srv_currently_usable(rsrv) && px->queue.length &&
(!(srv->flags & SRV_F_BACKUP) ||
(!px->srv_act &&
(srv == px->lbprm.fbck || (px->options & PR_O_USE_ALL_BK)))))
pp = pendconn_first(&px->queue.head);
if (!p && !pp)
@ -329,19 +335,9 @@ static struct pendconn *pendconn_process_next_strm(struct server *srv, struct pr
*/
void process_srv_queue(struct server *s)
{
struct server *ref = s->track ? s->track : s;
struct proxy *p = s->proxy;
int done = 0;
int maxconn;
int px_ok;
/* if a server is not usable or backup and must not be used
* to dequeue backend requests.
*/
px_ok = srv_currently_usable(ref) &&
(!(s->flags & SRV_F_BACKUP) ||
(!p->srv_act &&
(s == p->lbprm.fbck || (p->options & PR_O_USE_ALL_BK))));
maxconn = srv_dynamic_maxconn(s);
while (s->served < maxconn) {
@ -350,7 +346,7 @@ void process_srv_queue(struct server *s)
HA_SPIN_LOCK(QUEUE_LOCK, &s->queue.lock);
HA_SPIN_LOCK(QUEUE_LOCK, &p->queue.lock);
pc = pendconn_process_next_strm(s, p, px_ok);
pc = pendconn_process_next_strm(s, p);
HA_SPIN_UNLOCK(QUEUE_LOCK, &p->queue.lock);
HA_SPIN_UNLOCK(QUEUE_LOCK, &s->queue.lock);