diff --git a/programs/Makefile b/programs/Makefile index 912f9eff0..6c39c9830 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -40,6 +40,8 @@ CPPFLAGS+= -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \ -DXXH_NAMESPACE=ZSTD_ ifeq ($(OS),Windows_NT) # MinGW assumed CPPFLAGS += -D__USE_MINGW_ANSI_STDIO # compatibility with %zu formatting +else +DEBUGFLAGS_LD+= -rdynamic # Enable backtrace symbol names for Linux/Darwin endif CFLAGS ?= -O3 DEBUGFLAGS+=-Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ @@ -144,7 +146,7 @@ allVariants: zstd zstd-compress zstd-decompress zstd-small zstd-nolegacy $(ZSTDDECOMP_O): CFLAGS += $(ALIGN_LOOP) zstd : CPPFLAGS += $(THREAD_CPP) $(ZLIBCPP) $(LZMACPP) $(LZ4CPP) -zstd : LDFLAGS += $(THREAD_LD) $(ZLIBLD) $(LZMALD) $(LZ4LD) +zstd : LDFLAGS += $(THREAD_LD) $(ZLIBLD) $(LZMALD) $(LZ4LD) $(DEBUGFLAGS_LD) zstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) zstd : $(ZSTDLIB_FILES) zstdcli.o fileio.o bench.o datagen.o dibio.o @echo "$(THREAD_MSG)" @@ -158,6 +160,7 @@ endif .PHONY: zstd-release zstd-release: DEBUGFLAGS := +zstd-release: DEBUGFLAGS_LD := zstd-release: zstd zstd32 : CPPFLAGS += $(THREAD_CPP) diff --git a/programs/fileio.c b/programs/fileio.c index 5f10958d7..5f6b12e51 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -30,6 +30,10 @@ #include /* malloc, free */ #include /* strcmp, strlen */ #include /* errno */ +#include +#ifndef _WIN32 +#include /* backtrace, backtrace_symbols */ +#endif #if defined (_MSC_VER) # include @@ -124,8 +128,6 @@ static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; /*-************************************ * Signal (Ctrl-C trapping) **************************************/ -#include - static const char* g_artefact = NULL; static void INThandler(int sig) { @@ -157,7 +159,60 @@ static void clearHandler(void) } -/* ************************************************************ +/*-********************************************************* +* Termination signal trapping (Print debug stack trace) +***********************************************************/ +#define MAX_STACK_FRAMES 50 + +#ifndef _WIN32 +static void ABRThandler(int sig) { + const char* name; + void* addrlist[MAX_STACK_FRAMES]; + char** symbollist; + U32 addrlen, i; + + switch (sig) { + case SIGABRT: name = "SIGABRT"; break; + case SIGFPE: name = "SIGFPE"; break; + case SIGILL: name = "SIGILL"; break; + case SIGINT: name = "SIGINT"; break; + case SIGSEGV: name = "SIGSEGV"; break; + default: name = "UNKNOWN"; + } + + DISPLAY("Caught %s signal, printing stack:\n", name); + /* Retrieve current stack addresses. */ + addrlen = backtrace(addrlist, MAX_STACK_FRAMES); + 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 = ZSTD_START_SYMBOLLIST_FRAME; i < addrlen; i++) { + DISPLAY("%s\n", symbollist[i]); + } + free(symbollist); + /* Reset and raise the signal so default handler runs. */ + signal(sig, SIG_DFL); + raise(sig); +} +#endif + +void FIO_addAbortHandler() +{ +#ifndef _WIN32 + signal(SIGABRT, ABRThandler); + signal(SIGFPE, ABRThandler); + signal(SIGILL, ABRThandler); + signal(SIGSEGV, ABRThandler); + signal(SIGBUS, ABRThandler); +#endif +} + + +/*-************************************************************ * Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW ***************************************************************/ #if defined(_MSC_VER) && _MSC_VER >= 1400 diff --git a/programs/fileio.h b/programs/fileio.h index 69c83f71d..d25aee8dd 100644 --- a/programs/fileio.h +++ b/programs/fileio.h @@ -95,6 +95,9 @@ int FIO_decompressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles const char* dictFileName); +/* custom crash signal handler */ +void FIO_addAbortHandler(void); + #if defined (__cplusplus) } #endif diff --git a/programs/platform.h b/programs/platform.h index a550eb1a3..89eba37ec 100644 --- a/programs/platform.h +++ b/programs/platform.h @@ -148,6 +148,17 @@ static __inline int IS_CONSOLE(FILE* stdStream) { #endif +#ifndef ZSTD_START_SYMBOLLIST_FRAME +# ifdef __linux__ +# define ZSTD_START_SYMBOLLIST_FRAME 2 +# elif defined __APPLE__ +# define ZSTD_START_SYMBOLLIST_FRAME 4 +# else +# define ZSTD_START_SYMBOLLIST_FRAME 0 +# endif +#endif + + #if defined (__cplusplus) } #endif diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 0fccd34f9..3d4548a4b 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -511,6 +511,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 */ + FIO_addAbortHandler(); + /* command switches */ for (argNb=1; argNb