]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: lists: Avoid an infinite loop in MT_LIST_TRY_ADDQ().
authorOlivier Houchard <cognet@ci0.org>
Thu, 18 Feb 2021 22:55:30 +0000 (23:55 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 19 Feb 2021 15:47:20 +0000 (16:47 +0100)
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.

include/haproxy/list.h

index 6db2f92690786cffa6fbb4351f42447e157fd0d3..40929c4f8b5f933cbc454f58177a9f1433c9a4ce 100644 (file)
                        __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;                             \
+               p2 = _HA_ATOMIC_XCHG(&el->prev, MT_LIST_BUSY);             \
+               if (p2 != el) {                                            \
+                       if (p2 != MT_LIST_BUSY)                            \
+                               el->prev = p2;                             \
                        p->next = n;                                       \
                        __ha_barrier_store();                              \
                        lh->prev = p;                                      \
                        __ha_barrier_store();                              \
-                       if (n2 == MT_LIST_BUSY)                            \
+                       if (p2 == 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;                             \
+               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->next = el;                                     \
+                       el->prev = el;                                     \
                        __ha_barrier_store();                              \
                        lh->prev = p;                                      \
                        __ha_barrier_store();                              \
-                       if (p2 == MT_LIST_BUSY)                            \
+                       if (n2 == MT_LIST_BUSY)                            \
                                continue;                                  \
                        break;                                             \
                }                                                          \