BUG/MEDIUM: lists: Avoid an infinite loop in MT_LIST_TRY_ADDQ().

In MT_LIST_TRY_ADDQ(), deal with the "prev" field of the element before the
"next". If the element is the first in the list, then its next will
already have been locked when we locked list->prev->next, so locking it
again will fail, and we'll start over and over.

This should be backported to 2.3.
This commit is contained in:
Olivier Houchard 2021-02-18 23:55:30 +01:00 committed by Willy Tarreau
parent d8ea188058
commit 5567f41d0a

View file

@ -300,24 +300,11 @@
__ha_barrier_store(); \
continue; \
} \
n2 = _HA_ATOMIC_XCHG(&el->next, MT_LIST_BUSY); \
if (n2 != el) { /* element already linked */ \
if (n2 != MT_LIST_BUSY) \
el->next = n2; \
p->next = n; \
__ha_barrier_store(); \
lh->prev = p; \
__ha_barrier_store(); \
if (n2 == MT_LIST_BUSY) \
continue; \
break; \
} \
p2 = _HA_ATOMIC_XCHG(&el->prev, MT_LIST_BUSY); \
if (p2 != el) { \
if (p2 != MT_LIST_BUSY) \
el->prev = p2; \
p->next = n; \
el->next = el; \
__ha_barrier_store(); \
lh->prev = p; \
__ha_barrier_store(); \
@ -325,6 +312,19 @@
continue; \
break; \
} \
n2 = _HA_ATOMIC_XCHG(&el->next, MT_LIST_BUSY); \
if (n2 != el) { /* element already linked */ \
if (n2 != MT_LIST_BUSY) \
el->next = n2; \
p->next = n; \
el->prev = el; \
__ha_barrier_store(); \
lh->prev = p; \
__ha_barrier_store(); \
if (n2 == MT_LIST_BUSY) \
continue; \
break; \
} \
(el)->next = n; \
(el)->prev = p; \
__ha_barrier_store(); \