summaryrefslogtreecommitdiff
path: root/src/src/exim.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/src/exim.c')
-rw-r--r--src/src/exim.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/src/src/exim.c b/src/src/exim.c
index 1a4b44945..6fde16a9c 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -17,6 +17,11 @@ Also a few functions that don't naturally fit elsewhere. */
# include <gnu/libc-version.h>
#endif
+#ifndef _TIME_H
+# include <time.h>
+#endif
+#include <execinfo.h> /*XXX maybe glibc-only? */
+
#ifdef USE_GNUTLS
# include <gnutls/gnutls.h>
# if GNUTLS_VERSION_NUMBER < 0x030103 && !defined(DISABLE_OCSP)
@@ -24,10 +29,6 @@ Also a few functions that don't naturally fit elsewhere. */
# endif
#endif
-#ifndef _TIME_H
-# include <time.h>
-#endif
-
extern void init_lookup_list(void);
@@ -261,6 +262,29 @@ exit(1);
* Handler for SIGSEGV *
***********************************************/
+#define STACKDUMP_MAX 24
+void
+stackdump(ucontext_t * ucontext)
+{
+void * buf[STACKDUMP_MAX];
+char ** ss;
+int nptrs = backtrace(buf, STACKDUMP_MAX);
+
+log_write(0, LOG_MAIN|LOG_PANIC, "backtrace\n");
+log_write(0, LOG_MAIN|LOG_PANIC, "---\n");
+if ((ss = backtrace_symbols(buf, nptrs)))
+ {
+ for (int i = 0; i < nptrs; i++)
+ log_write(0, LOG_MAIN|LOG_PANIC, "\t%s\n", ss[i]);
+ free(ss);
+ }
+else
+ log_write(0, LOG_MAIN|LOG_PANIC, "backtrace_symbols: %s\n", strerror(errno));
+log_write(0, LOG_MAIN|LOG_PANIC, "---\n");
+}
+#undef STACKDUMP_MAX
+
+
static void
#ifdef SA_SIGINFO
segv_handler(int sig, siginfo_t * info, void * uctx)
@@ -281,6 +305,7 @@ else
log_write(0, LOG_MAIN|LOG_PANIC, "SIGSEGV (maybe attempt to write to immutable memory)");
if (process_info_len > 0)
log_write(0, LOG_MAIN|LOG_PANIC, "SIGSEGV (%.*s)", process_info_len, process_info);
+stackdump(uctx);
signal(SIGSEGV, SIG_DFL);
kill(getpid(), sig);
}
@@ -291,6 +316,7 @@ segv_handler(int sig)
log_write(0, LOG_MAIN|LOG_PANIC, "SIGSEGV (maybe attempt to write to immutable memory)");
if (process_info_len > 0)
log_write(0, LOG_MAIN|LOG_PANIC, "SIGSEGV (%.*s)", process_info_len, process_info);
+stackdump();
signal(SIGSEGV, SIG_DFL);
kill(getpid(), sig);
}