From a06574fc9701b056529825e9079421c29fd4a031 Mon Sep 17 00:00:00 2001 From: Casey McGinty Date: Thu, 6 Sep 2018 18:46:52 -0700 Subject: [PATCH] Print a stack trace on unexpected term signal (e.g. SIGABRT) For OSX and Linux, add a signal handler to SIGABRT, SGIFPE, SIGILL, SIGSEGV, and SIGBUS. When the program terminates unexpectedly the handler will print the current stack to the terminal to help determine the location of the failure. On OSX the output will look like: ``` Stack trace: 4 zstd 0x000000010927ed96 main + 16886 5 libdyld.dylib 0x00007fff767d1015 start + 1 6 ??? 0x0000000000000001 0x0 + 1 ``` On Linux the output will look like: ``` Stack trace: ./zstd() [0x4b8e1b] ./zstd() [0x4b928a] ./zstd() [0x403dc2] /lib64/libc.so.6(__libc_start_main+0xf5) [0x7f5e0fbb0445] ./zstd() [0x405754] ``` As is, the code does not function on WIN32. See also: https://oroboro.com/stack-trace-on-crash/ --- lib/common/zstd_common.c | 54 ++++++++++++++++++++++++++++++++++++++ lib/common/zstd_internal.h | 3 +++ programs/fileio.c | 2 +- programs/zstdcli.c | 4 +++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/lib/common/zstd_common.c b/lib/common/zstd_common.c index 6f05d240e..d3ad05730 100644 --- a/lib/common/zstd_common.c +++ b/lib/common/zstd_common.c @@ -15,10 +15,21 @@ ***************************************/ #include /* malloc, calloc, free */ #include /* memset */ +#include /* fprintf(), stderr */ +#include /* signal() */ +#ifndef _WIN32 +#include /* backtrace, backtrace_symbols, symbollist */ +#endif #include "error_private.h" #include "zstd_internal.h" +/*-************************************ +* Display Macros +**************************************/ +#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) + + /*-**************************************** * Version ******************************************/ @@ -79,3 +90,46 @@ void ZSTD_free(void* ptr, ZSTD_customMem customMem) free(ptr); } } + + +/*-********************************************************* +* Termination signal trapping (Print debug stack trace) +***********************************************************/ +#define MAX_STACK_FRAMES 50 + +#ifndef _WIN32 +static void ABRThandler(int sig) +{ + void* addrlist[MAX_STACK_FRAMES + 1]; + char** symbollist; + U32 addrlen, i; + + (void)sig; + + DISPLAY("Stack trace:\n"); + // Retrieve current stack addresses. + addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*)); + if (addrlen == 0) { + DISPLAY("\n"); + return; + } + // Create readable strings to each frame. + symbollist = backtrace_symbols(addrlist, addrlen); + // Print the stack trace, excluding calls handling the signal. + for (i = 4; i < addrlen; i++) { + DISPLAY("%s\n", symbollist[i]); + } + free(symbollist); +} +#endif + +void ZSTD_addAbortHandler() +{ +#ifndef _WIN32 + signal(SIGABRT, ABRThandler); + signal(SIGFPE, ABRThandler); + signal(SIGILL, ABRThandler); + signal(SIGSEGV, ABRThandler); + signal(SIGBUS, ABRThandler); +#endif +} diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index e75adfa61..b555dd828 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -206,6 +206,9 @@ void* ZSTD_malloc(size_t size, ZSTD_customMem customMem); void* ZSTD_calloc(size_t size, ZSTD_customMem customMem); void ZSTD_free(void* ptr, ZSTD_customMem customMem); +/* custom crash signal handler */ +void ZSTD_addAbortHandler(void); + MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */ { diff --git a/programs/fileio.c b/programs/fileio.c index 5f10958d7..7e9c31cb2 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -157,7 +157,7 @@ static void clearHandler(void) } -/* ************************************************************ +/*-************************************************************ * Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW ***************************************************************/ #if defined(_MSC_VER) && _MSC_VER >= 1400 diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 0fccd34f9..0688d44bc 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -39,6 +39,7 @@ #endif #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel */ #include "zstd.h" /* ZSTD_VERSION_STRING */ +#include "zstd_internal.h" /* ZSTD_addAbortHandler */ /*-************************************ @@ -511,6 +512,9 @@ int main(int argCount, const char* argv[]) if (exeNameMatch(programName, ZSTD_UNLZ4)) { operation=zom_decompress; FIO_setCompressionType(FIO_lz4Compression); } /* behave like unlz4, also supports multiple formats */ memset(&compressionParams, 0, sizeof(compressionParams)); + /* init crash handler */ + ZSTD_addAbortHandler(); + /* command switches */ for (argNb=1; argNb