]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: debug: let ha_dump_backtrace() dump a bit further for some callers
authorWilly Tarreau <w@1wt.eu>
Fri, 22 Jan 2021 13:48:34 +0000 (14:48 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 22 Jan 2021 13:48:34 +0000 (14:48 +0100)
The dump state is now passed to the function so that the caller can adjust
the behavior. A new series of 4 values allow to stop *after* dumping main
instead of before it or any of the usual loops. This allows to also report
BUG_ON() that could happen very high in the call graph (e.g. startup, or
the scheduler itself) while still understanding what the call path was.

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

index 5cec24326cf0c41e88ea57180214ee7ab136db50..dd1668db9e7dbbb868db33421a770f5b8a0d1de5 100644 (file)
@@ -28,7 +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_dump_backtrace(struct buffer *buf, const char *prefix, int dump);
 void ha_backtrace_to_stderr();
 void ha_thread_dump_all_to_trash();
 void ha_panic();
index 7d73fdc9e0a3658ea9920aba38213c8e37f60979..fc2de92f07d635c54afe2fcf00f5e74776588adf 100644 (file)
@@ -55,16 +55,22 @@ static unsigned int debug_prng()
 /* 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.
+ * the function does not appear in the call stack. The <dump> argument
+ * indicates what dump state to start from, and should usually be zero. It
+ * may be among the following values:
+ *   - 0: search usual callers before step 1, or directly jump to 2
+ *   - 1: skip usual callers before step 2
+ *   - 2: dump until polling loop, scheduler, or main() (excluded)
+ *   - 3: end
+ *   - 4-7: like 0 but stops *after* main.
  */
-void ha_dump_backtrace(struct buffer *buf, const char *prefix)
+void ha_dump_backtrace(struct buffer *buf, const char *prefix, int dump)
 {
        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)
@@ -77,43 +83,50 @@ void ha_dump_backtrace(struct buffer *buf, const char *prefix)
         * 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) {
+       for (j = 0; (j < nptrs || (dump & 3) < 2); j++) {
+               if (j == nptrs && !(dump & 3)) {
                        /* we failed to spot the starting point of the
                         * dump, let's start over dumping everything we
                         * have.
                         */
-                       dump = 2;
+                       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) {
+               if ((dump & 3) == 0) {
                        /* dump not started, will start *after*
                         * ha_thread_dump_all_to_trash, ha_panic and ha_backtrace_to_stderr
                         */
                        if (addr == ha_thread_dump_all_to_trash || addr == ha_panic ||
                            addr == ha_backtrace_to_stderr)
-                               dump = 1;
+                               dump++;
                        *buf = bak;
                        continue;
                }
 
-               if (dump == 1) {
+               if ((dump & 3) == 1) {
                        /* starting */
                        if (addr == ha_thread_dump_all_to_trash || addr == ha_panic ||
                            addr == ha_backtrace_to_stderr) {
                                *buf = bak;
                                continue;
                        }
-                       dump = 2;
+                       dump++;
                }
 
-               if (dump == 2) {
-                       /* dumping */
-                       if (addr == run_poll_loop || addr == main || addr == run_tasks_from_lists) {
-                               dump = 3;
+               if ((dump & 3) == 2) {
+                       /* still dumping */
+                       if (dump == 6) {
+                               /* we only stop *after* main and we must send the LF */
+                               if (addr == main) {
+                                       j = nptrs;
+                                       dump++;
+                               }
+                       }
+                       else if (addr == run_poll_loop || addr == main || addr == run_tasks_from_lists) {
+                               dump++;
                                *buf = bak;
                                break;
                        }
@@ -129,7 +142,7 @@ void ha_backtrace_to_stderr()
        char area[2048];
        struct buffer b = b_make(area, sizeof(area), 0, 0);
 
-       ha_dump_backtrace(&b, "  ");
+       ha_dump_backtrace(&b, "  ", 4);
        if (b.data)
                write(2, b.area, b.data);
 }
@@ -189,7 +202,7 @@ void ha_thread_dump(struct buffer *buf, int thr, int calling_tid)
                 * so that the compiler uses tail merging and the current
                 * function does not appear in the stack.
                 */
-               ha_dump_backtrace(buf, "             ");
+               ha_dump_backtrace(buf, "             ", 0);
        }
 }