]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: debug: extract the backtrace dumping code to its own function
authorWilly Tarreau <w@1wt.eu>
Fri, 22 Jan 2021 12:52:41 +0000 (13:52 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 22 Jan 2021 12:52:41 +0000 (13:52 +0100)
The backtrace dumping code was located into the thread dump function
but it looks particularly convenient to be able to call it to produce
a dump in other situations, so let's move it to its own function and
make sure it's called last in the function so that we can benefit from
tail merging to save one entry.

include/haproxy/debug.h
src/debug.c

index f25680d4b8bb40184e3ae3507f3eb9886aa1fb17..12456b5f59251b6dbdc9773f498757579eae5a47 100644 (file)
@@ -28,6 +28,7 @@ extern volatile unsigned long threads_to_dump;
 extern unsigned int debug_commands_issued;
 void ha_task_dump(struct buffer *buf, const struct task *task, const char *pfx);
 void ha_thread_dump(struct buffer *buf, int thr, int calling_tid);
+void ha_dump_backtrace(struct buffer *buf, const char *prefix);
 void ha_thread_dump_all_to_trash();
 void ha_panic();
 
index 3202814732180405cd7272116c22b723a585e0e3..465def26486832b6fb136e45e657ac4ba460841e 100644 (file)
@@ -52,6 +52,75 @@ static unsigned int debug_prng()
         return y;
 }
 
+/* dumps a backtrace of the current thread that is appended to buffer <buf>.
+ * Lines are prefixed with the string <prefix> which may be empty (used for
+ * indenting). It is recommended to use this at a function's tail so that
+ * the function does not appear in the call stack.
+ */
+void ha_dump_backtrace(struct buffer *buf, const char *prefix)
+{
+       struct buffer bak;
+       char pfx2[100];
+       void *callers[100];
+       int j, nptrs;
+       const void *addr;
+       int dump = 0;
+
+       nptrs = my_backtrace(callers, sizeof(callers)/sizeof(*callers));
+       if (!nptrs)
+               return;
+
+       if (snprintf(pfx2, sizeof(pfx2), "%s| ", prefix) > sizeof(pfx2))
+               pfx2[0] = 0;
+
+       /* The call backtrace_symbols_fd(callers, nptrs, STDOUT_FILENO would
+        * produce similar output to the following:
+        */
+       chunk_appendf(buf, "%scall trace(%d):\n", prefix, nptrs);
+       for (j = 0; (j < nptrs || dump < 2); j++) {
+               if (j == nptrs && !dump) {
+                       /* we failed to spot the starting point of the
+                        * dump, let's start over dumping everything we
+                        * have.
+                        */
+                       dump = 2;
+                       j = 0;
+               }
+               bak = *buf;
+               dump_addr_and_bytes(buf, pfx2, callers[j], 8);
+               addr = resolve_sym_name(buf, ": ", callers[j]);
+               if (dump == 0) {
+                       /* dump not started, will start *after*
+                        * ha_thread_dump_all_to_trash and ha_panic
+                        */
+                       if (addr == ha_thread_dump_all_to_trash || addr == ha_panic)
+                               dump = 1;
+                       *buf = bak;
+                       continue;
+               }
+
+               if (dump == 1) {
+                       /* starting */
+                       if (addr == ha_thread_dump_all_to_trash || addr == ha_panic) {
+                               *buf = bak;
+                               continue;
+                       }
+                       dump = 2;
+               }
+
+               if (dump == 2) {
+                       /* dumping */
+                       if (addr == run_poll_loop || addr == main || addr == run_tasks_from_lists) {
+                               dump = 3;
+                               *buf = bak;
+                               break;
+                       }
+               }
+               /* OK, line dumped */
+               chunk_appendf(buf, "\n");
+       }
+}
+
 /* Dumps to the buffer some known information for the desired thread, and
  * optionally extra info for the current thread. The dump will be appended to
  * the buffer, so the caller is responsible for preliminary initializing it.
@@ -103,63 +172,11 @@ void ha_thread_dump(struct buffer *buf, int thr, int calling_tid)
        if (stuck) {
                /* We only emit the backtrace for stuck threads in order not to
                 * waste precious output buffer space with non-interesting data.
+                * Please leave this as the last instruction in this function
+                * so that the compiler uses tail merging and the current
+                * function does not appear in the stack.
                 */
-               struct buffer bak;
-               void *callers[100];
-               int j, nptrs;
-               const void *addr;
-               int dump = 0;
-
-               nptrs = my_backtrace(callers, sizeof(callers)/sizeof(*callers));
-
-               /* The call backtrace_symbols_fd(callers, nptrs, STDOUT_FILENO)
-                  would produce similar output to the following: */
-
-               if (nptrs)
-                       chunk_appendf(buf, "             call trace(%d):\n", nptrs);
-
-               for (j = 0; nptrs && (j < nptrs || dump < 2); j++) {
-                       if (j == nptrs && !dump) {
-                               /* we failed to spot the starting point of the
-                                * dump, let's start over dumping everything we
-                                * have.
-                                */
-                               dump = 2;
-                               j = 0;
-                       }
-                       bak = *buf;
-                       dump_addr_and_bytes(buf, "             | ", callers[j], 8);
-                       addr = resolve_sym_name(buf, ": ", callers[j]);
-                       if (dump == 0) {
-                               /* dump not started, will start *after*
-                                * ha_thread_dump_all_to_trash and ha_panic
-                                */
-                               if (addr == ha_thread_dump_all_to_trash || addr == ha_panic)
-                                       dump = 1;
-                               *buf = bak;
-                               continue;
-                       }
-
-                       if (dump == 1) {
-                               /* starting */
-                               if (addr == ha_thread_dump_all_to_trash || addr == ha_panic) {
-                                       *buf = bak;
-                                       continue;
-                               }
-                               dump = 2;
-                       }
-
-                       if (dump == 2) {
-                               /* dumping */
-                               if (addr == run_poll_loop || addr == main || addr == run_tasks_from_lists) {
-                                       dump = 3;
-                                       *buf = bak;
-                                       break;
-                               }
-                       }
-                       /* OK, line dumped */
-                       chunk_appendf(buf, "\n");
-               }
+               ha_dump_backtrace(buf, "             ");
        }
 }