return 0;
}
+/* checks after a successful pendconn_add() if the connection ended up being
+ * alone with no active connection left to dequeue it. In such a case it will
+ * simply remove it from the queue, free it and return non-zero to inform the
+ * caller that it must try to add the connection again, otherwise it returns
+ * zero, indicating that the connection will be handled normally. The caller
+ * might have to drop SF_DIRECT and/or SF_ASSIGNED if the conn was on a proxy.
+ */
+int pendconn_must_try_again(struct pendconn *p)
+{
+ struct queue *q = p->queue;
+ struct proxy *px = q->px;
+ struct server *sv = q->sv;
+ int ret = 0;
+
+ if (likely(!HA_ATOMIC_LOAD(&p->node.node.leaf_p)))
+ goto leave;
+
+ /* for a server, we need at least one conn left on this server to
+ * find ours.
+ */
+ if (likely(sv && HA_ATOMIC_LOAD(&sv->served)))
+ goto leave;
+
+ /* for a backend, we need at least one conn left on any of this
+ * backend's servers to find ours.
+ */
+ if (likely(!sv && HA_ATOMIC_LOAD(&px->served)))
+ goto leave;
+
+ /* OK the situation is not safe anymore, we need to check if we're
+ * still in the queue under a lock.
+ */
+ HA_SPIN_LOCK(QUEUE_LOCK, &q->lock);
+ HA_SPIN_LOCK(QUEUE_LOCK, &p->del_lock);
+
+ if (p->node.node.leaf_p) {
+ eb32_delete(&p->node);
+ _HA_ATOMIC_DEC(&q->length);
+ _HA_ATOMIC_INC(&q->idx);
+ _HA_ATOMIC_DEC(&px->totpend);
+ ret = 1;
+ }
+
+ HA_SPIN_UNLOCK(QUEUE_LOCK, &p->del_lock);
+ HA_SPIN_UNLOCK(QUEUE_LOCK, &q->lock);
+
+ /* check if the connection was still queued. If not, it means its
+ * processing has begun so it's safe.
+ */
+ if (!ret)
+ goto leave;
+
+ /* The pendconn is not queued anymore and will not be so we're safe
+ * to free it.
+ */
+ p->strm->pend_pos = NULL;
+ pool_free(pool_head_pendconn, p);
+
+leave:
+ return ret;
+}
+
static enum act_return action_set_priority_class(struct act_rule *rule, struct proxy *px,
struct session *sess, struct stream *s, int flags)
{