]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
DEBUG: threads: display held locks in threads dumps
authorWilly Tarreau <w@1wt.eu>
Tue, 6 May 2025 03:11:56 +0000 (05:11 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 6 May 2025 03:20:37 +0000 (05:20 +0200)
Based on the lock history, we can spot some locks that are still held
by checking the last operation that happened on them: if it's not an
unlock, then we know the lock is held. In this case we append the list
after "locked:" with their label and state like below:

  U:QUEUE S:IDLE_CONNS U:IDLE_CONNS R:TASK_WQ U:TASK_WQ S:QUEUE S:QUEUE S:QUEUE locked: QUEUE(S)
  S:IDLE_CONNS U:IDLE_CONNS S:TASK_RQ U:TASK_RQ S:QUEUE U:QUEUE S:IDLE_CONNS locked: IDLE_CONNS(S)
  R:TASK_WQ S:TASK_WQ R:TASK_WQ S:TASK_WQ R:TASK_WQ S:TASK_WQ R:TASK_WQ locked: TASK_WQ(R)
  W:STK_TABLE W:STK_TABLE_UPDT U:STK_TABLE_UPDT W:STK_TABLE W:STK_TABLE_UPDT U:STK_TABLE_UPDT W:STK_TABLE W:STK_TABLE_UPDT locked: STK_TABLE(W) STK_TABLE_UPDT(W)

The format is slightly different (label(status)) so as to easily
differentiate them visually from the history.

src/debug.c

index 1d6b30a7a27589b12e6c1becc5995f37b4756c40..f92b5ff80843d77bc5d2a5789963cdae6efbf569 100644 (file)
@@ -355,7 +355,8 @@ void ha_thread_dump_one(struct buffer *buf, int is_caller)
 #if defined(USE_THREAD) && ((DEBUG_THREAD > 0) || defined(DEBUG_FULL))
        /* List the lock history */
        if (th_ctx->lock_history) {
-               int lkh, lkl;
+               int lkh, lkl, lbl;
+               int done;
 
                chunk_appendf(buf, "             lock_hist:");
                for (lkl = 7; lkl >= 0; lkl--) {
@@ -365,6 +366,29 @@ void ha_thread_dump_one(struct buffer *buf, int is_caller)
                        chunk_appendf(buf, " %c:%s",
                                      "URSW"[lkh & 3], lock_label((lkh >> 2) - 1));
                }
+
+               /* now rescan the list to only show those that remain */
+               done = 0;
+               for (lbl = 0; lbl < LOCK_LABELS; lbl++) {
+                       /* find the latest occurrence of each label */
+                       for (lkl = 0; lkl < 8; lkl++) {
+                               lkh = (th_ctx->lock_history >> (lkl * 8)) & 0xff;
+                               if (!lkh)
+                                       continue;
+                               if ((lkh >> 2) == lbl)
+                                       break;
+                       }
+                       if (lkl == 8) // not found
+                               continue;
+                       if ((lkh & 3) == _LK_UN)
+                               continue;
+                       if (!done)
+                               chunk_appendf(buf, " locked:");
+                       chunk_appendf(buf, " %s(%c)",
+                                     lock_label((lkh >> 2) - 1),
+                                     "URSW"[lkh & 3]);
+                       done++;
+               }
                chunk_appendf(buf, "\n");
        }
 #endif