changeset 4840:a0a38a306c17 HEAD

Since getting core dumps can be sometimes difficult, if we now do abort() ourself, we first log the backtrace. This works at least with Linux and Solaris.
author Timo Sirainen <tss@iki.fi>
date Sun, 19 Nov 2006 15:30:38 +0200
parents b8a9a0fd65c5
children c04ecbc7bdc8
files configure.in src/lib/Makefile.am src/lib/backtrace-string.c src/lib/backtrace-string.h src/lib/failures.c
diffstat 5 files changed, 113 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/configure.in	Sun Nov 19 01:35:37 2006 +0200
+++ b/configure.in	Sun Nov 19 15:30:38 2006 +0200
@@ -19,7 +19,7 @@
   sys/uio.h sys/sysmacros.h sys/resource.h sys/select.h libgen.h \
   sys/quota.h sys/fs/ufs_quota.h ufs/ufs/quota.h jfs/quota.h \
   mntent.h sys/mnttab.h sys/event.h sys/time.h sys/mkdev.h linux/dqblk_xfs.h \
-  xfs/xqm.h sasl.h sasl/sasl.h)
+  xfs/xqm.h sasl.h sasl/sasl.h execinfo.h ucontext.h)
 
 AC_ARG_ENABLE(ipv6,
 [  --enable-ipv6           Enable IPv6 support (default)],
@@ -411,7 +411,7 @@
                strcasecmp stricmp vsnprintf vsyslog writev pread \
 	       setrlimit setproctitle seteuid setreuid setegid setresgid \
 	       strtoull strtouq setpriority quotactl getmntent kqueue kevent \
-           getrusage)
+	       getrusage backtrace_symbols walkcontext)
 
 dnl * I/O loop function
 have_ioloop=no
--- a/src/lib/Makefile.am	Sun Nov 19 01:35:37 2006 +0200
+++ b/src/lib/Makefile.am	Sun Nov 19 15:30:38 2006 +0200
@@ -1,6 +1,7 @@
 noinst_LIBRARIES = liblib.a
 
 liblib_a_SOURCES = \
+	backtrace-string.c \
 	base64.c \
 	bsearch-insert-pos.c \
 	buffer.c \
@@ -89,6 +90,7 @@
 noinst_HEADERS = \
 	array.h \
 	array-decl.h \
+	backtrace-string.h \
 	base64.h \
 	bsearch-insert-pos.h \
 	buffer.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/backtrace-string.c	Sun Nov 19 15:30:38 2006 +0200
@@ -0,0 +1,87 @@
+/* Copyright (c) 2006 Timo Sirainen */
+
+#include "lib.h"
+#include "str.h"
+#include "backtrace-string.h"
+
+#define MAX_STACK_SIZE 30
+#define STACK_SKIP_COUNT 2
+
+#if defined(HAVE_BACKTRACE_SYMBOLS) && defined(HAVE_EXECINFO_H)
+/* Linux */
+#include <execinfo.h>
+#include <stdlib.h>
+
+int backtrace_append(string_t *str)
+{
+	void *stack[MAX_STACK_SIZE];
+	char **strings;
+	int ret, i;
+
+	ret = backtrace(stack, sizeof(stack)/sizeof(stack[0]));
+	if (ret <= STACK_SKIP_COUNT)
+		return -1;
+
+	strings = backtrace_symbols(stack, ret);
+	for (i = STACK_SKIP_COUNT; i < ret; i++) {
+		if (i > STACK_SKIP_COUNT)
+			str_append(str, " -> ");
+		str_append(str, strings[i]);
+	}
+	free(strings);
+	return 0;
+}
+#elif defined(HAVE_WALKCONTEXT) && defined(HAVE_UCONTEXT_H)
+/* Solaris */
+#include <ucontext.h>
+
+struct walk_context {
+	string_t *str;
+	unsigned int pos;
+};
+
+static int walk_callback(uintptr_t ptr, int signo __attr_unused__,
+			 void *context)
+{
+	struct walk_context *ctx = context;
+
+	if (ctx->pos >= STACK_SKIP_COUNT) {
+		if (ctx->pos > STACK_SKIP_COUNT)
+			str_append(ctx->str, " -> ");
+		str_printfa(ctx->str, "0x%p", (void *)ptr);
+	}
+	ctx->pos++;
+	return 0;
+}
+
+int backtrace_append(string_t *str)
+{
+	ucontext_t uc;
+	struct walk_context ctx;
+
+	if (getcontext(&uc) < 0)
+		return -1;
+
+	ctx.str = str;
+	ctx.pos = 0;
+	walkcontext(&uc, walk_callback, &ctx);
+	return 0;
+}
+#else
+int backtrace_append(string_t *str __attr_unused__)
+{
+	return -1;
+}
+#endif
+
+int backtrace_get(const char **backtrace_r)
+{
+	string_t *str;
+
+	str = t_str_new(512);
+	if (backtrace_append(str) < 0)
+		return -1;
+
+	*backtrace_r = str_c(str);
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/backtrace-string.h	Sun Nov 19 15:30:38 2006 +0200
@@ -0,0 +1,8 @@
+#ifndef __BACKTRACE_STRING_H
+#define __BACKTRACE_STRING_H
+
+/* Returns 0 if ok, -1 if failure. */
+int backtrace_append(string_t *str);
+int backtrace_get(const char **backtrace_r);
+
+#endif
--- a/src/lib/failures.c	Sun Nov 19 01:35:37 2006 +0200
+++ b/src/lib/failures.c	Sun Nov 19 15:30:38 2006 +0200
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "str.h"
+#include "backtrace-string.h"
 #include "write-full.h"
 #include "fd-close-on-exec.h"
 #include "printf-upper-bound.h"
@@ -120,7 +121,11 @@
 static void __attr_format__(1, 0)
 default_panic_handler(const char *format, va_list args)
 {
+	const char *backtrace;
+
 	(void)default_handler("Panic: ", log_fd, format, args);
+	if (backtrace_get(&backtrace) == 0)
+		i_error("Backtrace: %s", backtrace);
 	abort();
 }
 
@@ -290,8 +295,12 @@
 
 void i_syslog_panic_handler(const char *fmt, va_list args)
 {
+	const char *backtrace;
+
 	(void)syslog_handler(LOG_CRIT, fmt, args);
-        abort();
+	if (backtrace_get(&backtrace) == 0)
+		i_error("Backtrace: %s", backtrace);
+	abort();
 }
 
 void i_syslog_fatal_handler(int status, const char *fmt, va_list args)
@@ -384,7 +393,11 @@
 static void __attr_noreturn__ __attr_format__(1, 0)
 i_internal_panic_handler(const char *fmt, va_list args)
 {
+	const char *backtrace;
+
 	(void)internal_handler('F', fmt, args);
+	if (backtrace_get(&backtrace) == 0)
+		i_error("Backtrace: %s", backtrace);
         abort();
 }