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