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;
|
||||
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();
|
||||
|
|
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>.
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue