diff --git a/doc/internals/watchdog.txt b/doc/internals/watchdog.txt index cb212b790..b2faa5140 100644 --- a/doc/internals/watchdog.txt +++ b/doc/internals/watchdog.txt @@ -85,6 +85,12 @@ to point to the target buffer. The thread_dump_buffer has 4 possible values: will keep their own copy of their own dump so that it can be later found in the core file for inspection. +A copy of the last valid thread_dump_buffer used is kept in last_dump_buffer, +for easier post-mortem analysis. This one may be NULL or even invalid, but +usually during a panic it will be valid, and may reveal useful hints even if it +still contains the dump of the last warning. Usually this will point to a trash +buffer or to stack area. + ha_thread_dump_fill() then either directly calls ha_thread_dump_one() if the target thread is the current thread, or sends the target thread DEBUGSIG (SIGURG) if it's a different thread. This signal is initialized at boot time diff --git a/include/haproxy/tinfo-t.h b/include/haproxy/tinfo-t.h index 95604b0f5..229f0a4c2 100644 --- a/include/haproxy/tinfo-t.h +++ b/include/haproxy/tinfo-t.h @@ -188,6 +188,7 @@ struct thread_ctx { unsigned long long out_bytes; /* total #of bytes emitted */ unsigned long long spliced_out_bytes; /* total #of bytes emitted though a kernel pipe */ struct buffer *thread_dump_buffer; /* NULL out of dump, 0x02=to alloc, valid during a dump, |0x01 once done */ + struct buffer *last_dump_buffer; /* Copy of last buffer used for a dump; may be NULL or invalid; for post-mortem only */ unsigned long long total_streams; /* Total number of streams created on this thread */ unsigned int stream_cnt; /* Number of streams attached to this thread */ diff --git a/src/debug.c b/src/debug.c index d4a61f27b..8a5a07f89 100644 --- a/src/debug.c +++ b/src/debug.c @@ -319,6 +319,9 @@ void ha_thread_dump_one(int thr, int from_signal) unsigned long long n = now_cpu_time_thread(thr); int stuck = !!(ha_thread_ctx[thr].flags & TH_FL_STUCK); + /* keep a copy of the dump pointer for post-mortem analysis */ + HA_ATOMIC_STORE(&ha_thread_ctx[thr].last_dump_buffer, buf); + chunk_appendf(buf, "%c%cThread %-2u: id=0x%llx act=%d glob=%d wq=%d rq=%d tl=%d tlsz=%d rqsz=%d\n" " %2u/%-2u stuck=%d prof=%d",