From 8c0a7c0acc13c019517dc1d9f3c9bcb0cd3a08e3 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Tue, 1 Aug 2017 22:57:36 -0400 Subject: [PATCH] Add support for printing backtraces on segfault Enabled in debug mode (make all-debug). --- configure.ac | 2 +- contrib/config.make-Darwin | 1 + include/tig/tig.h | 4 ++++ include/tig/util.h | 2 ++ src/tig.c | 42 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index fc9ddb608..4b914e821 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ m4_pattern_forbid([^AX_]) AC_PROG_CC -AC_CHECK_HEADERS([stdint.h stdlib.h string.h sys/time.h unistd.h wordexp.h]) +AC_CHECK_HEADERS([execinfo.h stdint.h stdlib.h string.h sys/time.h unistd.h wordexp.h]) AC_CHECK_FUNCS([gettimeofday]) AC_CHECK_DECLS([environ]) AC_CHECK_DECLS([errno], [], [], [#include ]) diff --git a/contrib/config.make-Darwin b/contrib/config.make-Darwin index cd7ffb829..980a7fcf5 100644 --- a/contrib/config.make-Darwin +++ b/contrib/config.make-Darwin @@ -3,6 +3,7 @@ # Work-around for Homebrew-based xmlto. export XML_CATALOG_FILES=/usr/local/etc/xml/catalog +TIG_CFLAGS += -DHAVE_EXECINFO_H TIG_LDLIBS = -liconv NCURSES_DIR = $(wildcard /usr/local/opt/ncurses) diff --git a/include/tig/tig.h b/include/tig/tig.h index 6af1bd404..d4299b400 100644 --- a/include/tig/tig.h +++ b/include/tig/tig.h @@ -60,6 +60,10 @@ #include #include +#ifdef HAVE_EXECINFO_H +#include +#endif + /* ncurses(3): Must be defined to have extended wide-character functions. */ #define _XOPEN_SOURCE_EXTENDED 1 diff --git a/include/tig/util.h b/include/tig/util.h index 6af76da2e..b2e76375e 100644 --- a/include/tig/util.h +++ b/include/tig/util.h @@ -116,5 +116,7 @@ name(type **mem, size_t size, size_t increase) \ return tmp; \ } +void sigsegv_handler(int sig); + #endif /* vim: set ts=8 sw=8 noexpandtab: */ diff --git a/src/tig.c b/src/tig.c index 8047f7553..3e6d1bb19 100644 --- a/src/tig.c +++ b/src/tig.c @@ -627,6 +627,43 @@ handle_mouse_event(void) } #endif +/* + * Error handling. + * + * Inspired by code from src/util.c in ELinks + * (f86be659718c0cd0a67f88b42f07044c23d0d028). + */ + +#ifdef DEBUG +void +sigsegv_handler(int sig) +{ + if (die_callback) + die_callback(); + + fputs("Tig crashed!\n\n" + "Please report this issue along with all info printed below to\n\n" + " https://github.com/jonas/tig/issues/new\n\n", stderr); + + fputs("Tig version: ", stderr); + fputs(TIG_VERSION, stderr); + fputs("\n\n", stderr); + +#ifdef HAVE_EXECINFO_H + { + /* glibc way of doing this */ + void *stack[20]; + size_t size = backtrace(stack, 20); + + backtrace_symbols_fd(stack, size, STDERR_FILENO); + } +#endif + + /* The fastest way OUT! */ + abort(); +} +#endif + struct key_combo { enum request request; struct keymap *keymap; @@ -690,6 +727,11 @@ main(int argc, const char *argv[]) if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) die("Failed to setup signal handler"); +#ifdef DEBUG + if (signal(SIGSEGV, sigsegv_handler) == SIG_ERR) + die("Failed to setup signal handler"); +#endif + if (setlocale(LC_ALL, "")) { codeset = nl_langinfo(CODESET); }