>From aff37074abd0431e5bbcad370ceea3c9a2ed56c4 Mon Sep 17 00:00:00 2001 From: Brand Huntsman
Date: Fri, 19 Jan 2018 04:42:50 -0700 Subject: [PATCH] restore terminal and print backtrace for segfaults and assertions Signed-off-by: Brand Huntsman --- src/Makefile.am | 3 +++ src/nano.c | 39 ++++++++++++++++++++++++++++++++++++--- src/nano.h | 10 +++++++++- src/proto.h | 2 ++ 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 625434c2..f9422e47 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,9 @@ AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\" \ -I$(top_builddir)/lib -I$(top_srcdir)/lib +# -rdynamic is needed by print_backtrace() to show function names +LDFLAGS = -rdynamic + CLEANFILES = revision.h if BUILDING_FROM_GIT diff --git a/src/nano.c b/src/nano.c index a21625cf..dd2519ec 100644 --- a/src/nano.c +++ b/src/nano.c @@ -549,6 +549,13 @@ void say_there_is_no_help(void) } #endif +/* Make nano exit semi-gracefully during a crash. */ +void crash_finish(void) +{ + endwin(); + tcsetattr(0, TCSANOW, &oldterm); +} + /* Make nano exit gracefully. */ void finish(void) { @@ -1890,8 +1897,37 @@ void do_output(char *output, size_t output_len, bool allow_cntrls) update_line(openfile->current, openfile->current_x); } +void print_backtrace(int skip_to) +{ + void *callstack[16]; + int i, frames = backtrace(callstack, 16); + char **strings = backtrace_symbols(callstack, frames); + for (i = skip_to + 1; i < frames; i++){ + /* +1 skips print_backtrace() */ + IGNORE_CALL_RESULT(write(2, "| ", 3)); + IGNORE_CALL_RESULT(write(2, strings[i], strlen(strings[i]))); + IGNORE_CALL_RESULT(write(2, "\n", 1)); + } + free(strings); + exit(1); +} + +static const char segfault_msg[] = "Segmentation fault\n"; +static void segfault_handler(int nothing) +{ + crash_finish(); + IGNORE_CALL_RESULT(write(2, segfault_msg, sizeof(segfault_msg))); + print_backtrace(1); /* +1 skips segfault_handler() */ +} + int main(int argc, char **argv) { + /* Initialize segfault handler. */ + signal(SIGSEGV, segfault_handler); + + /* Back up the terminal settings so that they can be restored. */ + tcgetattr(0, &oldterm); + int stdin_flags, optchr; #if defined(ENABLED_WRAPORJUSTIFY) && defined(ENABLE_NANORC) bool fill_used = FALSE; @@ -1985,9 +2021,6 @@ int main(int argc, char **argv) console = (getenv("DISPLAY") == NULL); #endif - /* Back up the terminal settings so that they can be restored. */ - tcgetattr(0, &oldterm); - /* Get the state of standard input and ensure it uses blocking mode. */ stdin_flags = fcntl(0, F_GETFL, 0); if (stdin_flags != -1) diff --git a/src/nano.h b/src/nano.h index 55abf1e8..edbb9c5b 100644 --- a/src/nano.h +++ b/src/nano.h @@ -120,7 +120,15 @@ #include