MINOR: debug: let ha_dump_backtrace() dump a bit further for some callers
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.
This commit is contained in:
parent
5baf4fe31a
commit
2bfce7e424
|
@ -28,7 +28,7 @@ extern volatile unsigned long threads_to_dump;
|
||||||
extern unsigned int debug_commands_issued;
|
extern unsigned int debug_commands_issued;
|
||||||
void ha_task_dump(struct buffer *buf, const struct task *task, const char *pfx);
|
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_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_backtrace_to_stderr();
|
||||||
void ha_thread_dump_all_to_trash();
|
void ha_thread_dump_all_to_trash();
|
||||||
void ha_panic();
|
void ha_panic();
|
||||||
|
|
45
src/debug.c
45
src/debug.c
|
@ -55,16 +55,22 @@ static unsigned int debug_prng()
|
||||||
/* dumps a backtrace of the current thread that is appended to buffer <buf>.
|
/* 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
|
* 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
|
* 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;
|
struct buffer bak;
|
||||||
char pfx2[100];
|
char pfx2[100];
|
||||||
void *callers[100];
|
void *callers[100];
|
||||||
int j, nptrs;
|
int j, nptrs;
|
||||||
const void *addr;
|
const void *addr;
|
||||||
int dump = 0;
|
|
||||||
|
|
||||||
nptrs = my_backtrace(callers, sizeof(callers)/sizeof(*callers));
|
nptrs = my_backtrace(callers, sizeof(callers)/sizeof(*callers));
|
||||||
if (!nptrs)
|
if (!nptrs)
|
||||||
|
@ -77,43 +83,50 @@ void ha_dump_backtrace(struct buffer *buf, const char *prefix)
|
||||||
* produce similar output to the following:
|
* produce similar output to the following:
|
||||||
*/
|
*/
|
||||||
chunk_appendf(buf, "%scall trace(%d):\n", prefix, nptrs);
|
chunk_appendf(buf, "%scall trace(%d):\n", prefix, nptrs);
|
||||||
for (j = 0; (j < nptrs || dump < 2); j++) {
|
for (j = 0; (j < nptrs || (dump & 3) < 2); j++) {
|
||||||
if (j == nptrs && !dump) {
|
if (j == nptrs && !(dump & 3)) {
|
||||||
/* we failed to spot the starting point of the
|
/* we failed to spot the starting point of the
|
||||||
* dump, let's start over dumping everything we
|
* dump, let's start over dumping everything we
|
||||||
* have.
|
* have.
|
||||||
*/
|
*/
|
||||||
dump = 2;
|
dump += 2;
|
||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
bak = *buf;
|
bak = *buf;
|
||||||
dump_addr_and_bytes(buf, pfx2, callers[j], 8);
|
dump_addr_and_bytes(buf, pfx2, callers[j], 8);
|
||||||
addr = resolve_sym_name(buf, ": ", callers[j]);
|
addr = resolve_sym_name(buf, ": ", callers[j]);
|
||||||
if (dump == 0) {
|
if ((dump & 3) == 0) {
|
||||||
/* dump not started, will start *after*
|
/* dump not started, will start *after*
|
||||||
* ha_thread_dump_all_to_trash, ha_panic and ha_backtrace_to_stderr
|
* ha_thread_dump_all_to_trash, ha_panic and ha_backtrace_to_stderr
|
||||||
*/
|
*/
|
||||||
if (addr == ha_thread_dump_all_to_trash || addr == ha_panic ||
|
if (addr == ha_thread_dump_all_to_trash || addr == ha_panic ||
|
||||||
addr == ha_backtrace_to_stderr)
|
addr == ha_backtrace_to_stderr)
|
||||||
dump = 1;
|
dump++;
|
||||||
*buf = bak;
|
*buf = bak;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dump == 1) {
|
if ((dump & 3) == 1) {
|
||||||
/* starting */
|
/* starting */
|
||||||
if (addr == ha_thread_dump_all_to_trash || addr == ha_panic ||
|
if (addr == ha_thread_dump_all_to_trash || addr == ha_panic ||
|
||||||
addr == ha_backtrace_to_stderr) {
|
addr == ha_backtrace_to_stderr) {
|
||||||
*buf = bak;
|
*buf = bak;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
dump = 2;
|
dump++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dump == 2) {
|
if ((dump & 3) == 2) {
|
||||||
/* dumping */
|
/* still dumping */
|
||||||
if (addr == run_poll_loop || addr == main || addr == run_tasks_from_lists) {
|
if (dump == 6) {
|
||||||
dump = 3;
|
/* 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;
|
*buf = bak;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +142,7 @@ void ha_backtrace_to_stderr()
|
||||||
char area[2048];
|
char area[2048];
|
||||||
struct buffer b = b_make(area, sizeof(area), 0, 0);
|
struct buffer b = b_make(area, sizeof(area), 0, 0);
|
||||||
|
|
||||||
ha_dump_backtrace(&b, " ");
|
ha_dump_backtrace(&b, " ", 4);
|
||||||
if (b.data)
|
if (b.data)
|
||||||
write(2, b.area, 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
|
* so that the compiler uses tail merging and the current
|
||||||
* function does not appear in the stack.
|
* function does not appear in the stack.
|
||||||
*/
|
*/
|
||||||
ha_dump_backtrace(buf, " ");
|
ha_dump_backtrace(buf, " ", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue