Index: configure
===================================================================
--- configure	(revision e1e5bd67665452dbc300234b1b4ab7709e83f85d)
+++ configure	(revision 0d2cd10fba86011a01a1c52c0db2e98660efa1de)
@@ -485,4 +485,14 @@
 '
 
+BACKTRACE_TESTCODE='
+#include <execinfo.h>
+
+int main()
+{
+	void *trace[16];
+	return backtrace(trace, 16);
+}
+'
+
 detect_resolv_dynamic()
 {
@@ -582,4 +592,17 @@
 }
 
+detect_backtrace()
+{
+	TMPFILE=$(mktemp /tmp/bitlbee-configure.XXXXXX)
+	ret=1
+	echo "$BACKTRACE_TESTCODE" | $CC -o $TMPFILE -x c -  >/dev/null 2>/dev/null
+	if [ "$?" = "0" ]; then
+		ret=0
+	fi
+
+	rm -f $TMPFILE
+	return $ret
+}
+
 if [ "$ssl" = "auto" ]; then
 	detect_gnutls
@@ -647,4 +670,8 @@
 fi
 
+if detect_backtrace; then
+	echo '#define HAVE_BACKTRACE' >> config.h
+	echo '#define CRASHFILE "'$config'crash.log"' >> config.h
+fi
 
 STORAGES="xml"
Index: unix.c
===================================================================
--- unix.c	(revision e1e5bd67665452dbc300234b1b4ab7709e83f85d)
+++ unix.c	(revision 0d2cd10fba86011a01a1c52c0db2e98660efa1de)
@@ -46,4 +46,8 @@
 #endif
 
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+#endif
+
 global_t global;        /* Against global namespace pollution */
 
@@ -63,4 +67,7 @@
 	char *old_cwd = NULL;
 	struct sigaction sig, old;
+#ifdef HAVE_BACKTRACE
+	void *unused[1];
+#endif
 
 	/* Required to make iconv to ASCII//TRANSLIT work. This makes BitlBee
@@ -175,4 +182,11 @@
 	sigaction(SIGINT, &sig, &old);
 	sigaction(SIGTERM, &sig, &old);
+
+#ifdef HAVE_BACKTRACE
+	/* As per the backtrace(3) man page, call this outside of the signal
+	 * handler once to ensure any dynamic libraries are loaded in an
+	 * async-signal-safe environment to prevent deadlocks */
+	backtrace(unused, 1);
+#endif
 
 	if (!getuid() || !geteuid()) {
@@ -292,4 +306,55 @@
 }
 
+#ifdef HAVE_BACKTRACE
+/* Writes a backtrace to (usually) /var/lib/bitlbee/crash.log
+ * No malloc allowed means not a lot can be written to that file */
+static void sighandler_crash_backtrace()
+{
+	int fd, mapsfd;
+	int size;
+	void *trace[128];
+	const char message[] = "## " PACKAGE " crashed\n"
+		"## Version: " BITLBEE_VERSION "\n"
+		"## Configure args: " BITLBEE_CONFIGURE_ARGS "\n"
+		"##\n"
+		"## Backtrace:\n\n";
+	const char message2[] = "\n"
+		"## Hint: To get details on addresses use\n"
+		"##   addr2line -e <binary> <address>\n"
+		"## or\n"
+		"##   gdb <binary> -ex 'l *<address>' -ex q\n"
+		"## where <binary> is a filename from above and <address> is the part between (...)\n"
+		"##\n\n";
+	const char message3[] = "\n## End of memory maps. See above for the backtrace\n\n";
+
+	fd = open(CRASHFILE, O_WRONLY | O_APPEND | O_CREAT, 0600);
+
+	if (fd == -1 || write(fd, message, sizeof(message) - 1) == -1) {
+		return;
+	}
+
+	size = backtrace(trace, 128);
+	backtrace_symbols_fd(trace, size, fd);
+
+	(void) write(fd, message2, sizeof(message2) - 1);
+
+	/* a bit too linux-specific, so fail gracefully */
+	mapsfd = open("/proc/self/maps", O_RDONLY, 0);
+
+	if (mapsfd != -1) {
+		char buf[4096] = {0};
+		ssize_t bytes;
+
+		while ((bytes = read(mapsfd, buf, sizeof(buf))) > 0) {
+			(void) write(fd, buf, bytes);
+		}
+		(void) close(mapsfd);
+		(void) write(fd, message3, sizeof(message3) - 1);
+	}
+
+	(void) close(fd);
+}
+#endif
+
 /* Signal handler for SIGSEGV
  * A desperate attempt to tell the user that everything is wrong in the world.
@@ -298,7 +363,9 @@
 {
 	GSList *l;
-	int unused G_GNUC_UNUSED;
-	const char *message = "ERROR :BitlBee crashed! (SIGSEGV received)\r\n";
-	int len = strlen(message);
+	const char message[] = "ERROR :BitlBee crashed! (SIGSEGV received)\r\n"
+#ifdef HAVE_BACKTRACE
+		"ERROR :Writing backtrace to " CRASHFILE "\r\n"
+#endif
+		"ERROR :This is a bug either in BitlBee or a plugin, ask us on IRC if unsure\r\n";
 
 	for (l = irc_connection_list; l; l = l->next) {
@@ -306,8 +373,12 @@
 		sock_make_blocking(irc->fd);
 		if (irc->sendbuffer) {
-			unused = write(irc->fd, irc->sendbuffer, strlen(irc->sendbuffer));
-		}
-		unused = write(irc->fd, message, len);
-	}
+			(void) write(irc->fd, irc->sendbuffer, strlen(irc->sendbuffer));
+		}
+		(void) write(irc->fd, message, sizeof(message) - 1);
+	}
+
+#ifdef HAVE_BACKTRACE
+	sighandler_crash_backtrace();
+#endif
 
 	raise(signal);
