Dump stack trace on crash
This commit is contained in:
parent
f511ad2a67
commit
76a68fb071
2 changed files with 138 additions and 2 deletions
|
@ -13,6 +13,7 @@ endif( CMAKE_SYSTEM_NAME STREQUAL "Linux" )
|
||||||
|
|
||||||
include( FindPkgConfig )
|
include( FindPkgConfig )
|
||||||
include( CheckLibraryExists )
|
include( CheckLibraryExists )
|
||||||
|
include( CheckCSourceCompiles )
|
||||||
pkg_check_modules( X11 REQUIRED x11 xcomposite xdamage xinerama xrender xrandr>=1.3 )
|
pkg_check_modules( X11 REQUIRED x11 xcomposite xdamage xinerama xrender xrandr>=1.3 )
|
||||||
pkg_check_modules( PANGOCAIRO REQUIRED pangocairo )
|
pkg_check_modules( PANGOCAIRO REQUIRED pangocairo )
|
||||||
pkg_check_modules( PANGO REQUIRED pango )
|
pkg_check_modules( PANGO REQUIRED pango )
|
||||||
|
@ -21,6 +22,19 @@ pkg_check_modules( GLIB2 REQUIRED glib-2.0 )
|
||||||
pkg_check_modules( GOBJECT2 REQUIRED gobject-2.0 )
|
pkg_check_modules( GOBJECT2 REQUIRED gobject-2.0 )
|
||||||
pkg_check_modules( IMLIB2 REQUIRED imlib2>=1.4.2 )
|
pkg_check_modules( IMLIB2 REQUIRED imlib2>=1.4.2 )
|
||||||
|
|
||||||
|
check_c_source_compiles(
|
||||||
|
"#include <stdlib.h>\n#include <execinfo.h>\nint main () { backtrace(NULL, 0); }"
|
||||||
|
BACKTRACE_LIBC)
|
||||||
|
|
||||||
|
if(BACKTRACE_LIBC)
|
||||||
|
set(BACKTRACE_LIBC_FOUND TRUE)
|
||||||
|
set(BACKTRACE_L_FLAGS "-rdynamic")
|
||||||
|
else()
|
||||||
|
pkg_check_modules( UNWIND libunwind )
|
||||||
|
pkg_check_modules( EXECINFO execinfo )
|
||||||
|
set(BACKTRACE_L_FLAGS "")
|
||||||
|
endif()
|
||||||
|
|
||||||
if( ENABLE_RSVG )
|
if( ENABLE_RSVG )
|
||||||
pkg_check_modules( RSVG librsvg-2.0>=2.14.0 )
|
pkg_check_modules( RSVG librsvg-2.0>=2.14.0 )
|
||||||
endif( ENABLE_RSVG )
|
endif( ENABLE_RSVG )
|
||||||
|
@ -129,6 +143,18 @@ if( ENABLE_UEVENT )
|
||||||
set( SOURCES ${SOURCES} src/util/uevent.c)
|
set( SOURCES ${SOURCES} src/util/uevent.c)
|
||||||
endif( ENABLE_UEVENT )
|
endif( ENABLE_UEVENT )
|
||||||
|
|
||||||
|
if(BACKTRACE_LIBC_FOUND)
|
||||||
|
add_definitions( -DENABLE_EXECINFO )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if( UNWIND_FOUND )
|
||||||
|
add_definitions( -DENABLE_LIBUNWIND )
|
||||||
|
endif( UNWIND_FOUND )
|
||||||
|
|
||||||
|
if( EXECINFO_FOUND )
|
||||||
|
add_definitions( -DENABLE_EXECINFO )
|
||||||
|
endif( EXECINFO_FOUND )
|
||||||
|
|
||||||
if( ENABLE_TINT2CONF )
|
if( ENABLE_TINT2CONF )
|
||||||
add_definitions( -DHAVE_VERSION_H )
|
add_definitions( -DHAVE_VERSION_H )
|
||||||
add_subdirectory( src/tint2conf )
|
add_subdirectory( src/tint2conf )
|
||||||
|
@ -166,7 +192,9 @@ target_link_libraries( tint2 ${X11_LIBRARIES}
|
||||||
${CAIRO_LIBRARIES}
|
${CAIRO_LIBRARIES}
|
||||||
${GLIB2_LIBRARIES}
|
${GLIB2_LIBRARIES}
|
||||||
${GOBJECT2_LIBRARIES}
|
${GOBJECT2_LIBRARIES}
|
||||||
${IMLIB2_LIBRARIES} )
|
${IMLIB2_LIBRARIES}
|
||||||
|
${UNWIND_LIBRARIES}
|
||||||
|
${EXECINFO_LIBRARIES} )
|
||||||
if( ENABLE_RSVG )
|
if( ENABLE_RSVG )
|
||||||
target_link_libraries( tint2 ${RSVG_LIBRARIES} )
|
target_link_libraries( tint2 ${RSVG_LIBRARIES} )
|
||||||
endif( ENABLE_RSVG )
|
endif( ENABLE_RSVG )
|
||||||
|
@ -181,7 +209,7 @@ target_link_libraries( tint2 m )
|
||||||
|
|
||||||
add_dependencies( tint2 version )
|
add_dependencies( tint2 version )
|
||||||
set_target_properties( tint2 PROPERTIES COMPILE_FLAGS "-Wall -Wpointer-arith -fno-strict-aliasing -pthread -std=c99 ${ASAN_C_FLAGS}" )
|
set_target_properties( tint2 PROPERTIES COMPILE_FLAGS "-Wall -Wpointer-arith -fno-strict-aliasing -pthread -std=c99 ${ASAN_C_FLAGS}" )
|
||||||
set_target_properties( tint2 PROPERTIES LINK_FLAGS "-pthread -fno-strict-aliasing ${ASAN_L_FLAGS}" )
|
set_target_properties( tint2 PROPERTIES LINK_FLAGS "-pthread -fno-strict-aliasing ${ASAN_L_FLAGS} ${BACKTRACE_L_FLAGS}" )
|
||||||
|
|
||||||
install( TARGETS tint2 DESTINATION bin )
|
install( TARGETS tint2 DESTINATION bin )
|
||||||
install( FILES tint2.svg DESTINATION ${DATADIR}/icons/hicolor/scalable/apps )
|
install( FILES tint2.svg DESTINATION ${DATADIR}/icons/hicolor/scalable/apps )
|
||||||
|
|
108
src/tint.c
108
src/tint.c
|
@ -51,6 +51,15 @@
|
||||||
#include "xsettings-client.h"
|
#include "xsettings-client.h"
|
||||||
#include "uevent.h"
|
#include "uevent.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_LIBUNWIND
|
||||||
|
#define UNW_LOCAL_ONLY
|
||||||
|
#include <libunwind.h>
|
||||||
|
#else
|
||||||
|
#ifdef ENABLE_EXECINFO
|
||||||
|
#include <execinfo.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// Drag and Drop state variables
|
// Drag and Drop state variables
|
||||||
Window dnd_source_window;
|
Window dnd_source_window;
|
||||||
Window dnd_target_window;
|
Window dnd_target_window;
|
||||||
|
@ -104,6 +113,98 @@ void signal_handler(int sig)
|
||||||
signal_pending = sig;
|
signal_pending = sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_string(int fd, const char *s)
|
||||||
|
{
|
||||||
|
int len = strlen(s);
|
||||||
|
while (len > 0) {
|
||||||
|
int count = write(fd, s, len);
|
||||||
|
if (count >= 0) {
|
||||||
|
s += count;
|
||||||
|
len -= count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *signal_name(int sig)
|
||||||
|
{
|
||||||
|
switch (sig) {
|
||||||
|
case SIGHUP: return "SIGHUP: Hangup (POSIX).";
|
||||||
|
case SIGINT: return "SIGINT: Interrupt (ANSI).";
|
||||||
|
case SIGQUIT: return "SIGQUIT: Quit (POSIX).";
|
||||||
|
case SIGILL: return "SIGILL: Illegal instruction (ANSI).";
|
||||||
|
case SIGTRAP: return "SIGTRAP: Trace trap (POSIX).";
|
||||||
|
case SIGABRT: return "SIGABRT/SIGIOT: Abort (ANSI) / IOT trap (4.2 BSD).";
|
||||||
|
case SIGBUS: return "SIGBUS: BUS error (4.2 BSD).";
|
||||||
|
case SIGFPE: return "SIGFPE: Floating-point exception (ANSI).";
|
||||||
|
case SIGKILL: return "SIGKILL: Kill, unblockable (POSIX).";
|
||||||
|
case SIGUSR1: return "SIGUSR1: User-defined signal 1 (POSIX).";
|
||||||
|
case SIGSEGV: return "SIGSEGV: Segmentation violation (ANSI).";
|
||||||
|
case SIGUSR2: return "SIGUSR2: User-defined signal 2 (POSIX).";
|
||||||
|
case SIGPIPE: return "SIGPIPE: Broken pipe (POSIX).";
|
||||||
|
case SIGALRM: return "SIGALRM: Alarm clock (POSIX).";
|
||||||
|
case SIGTERM: return "SIGTERM: Termination (ANSI).";
|
||||||
|
case SIGSTKFLT: return "SIGSTKFLT: Stack fault.";
|
||||||
|
case SIGCHLD: return "SIGCHLD: Child status has changed (POSIX).";
|
||||||
|
case SIGCONT: return "SIGCONT: Continue (POSIX).";
|
||||||
|
case SIGSTOP: return "SIGSTOP: Stop, unblockable (POSIX).";
|
||||||
|
case SIGTSTP: return "SIGTSTP: Keyboard stop (POSIX).";
|
||||||
|
case SIGTTIN: return "SIGTTIN: Background read from tty (POSIX).";
|
||||||
|
case SIGTTOU: return "SIGTTOU: Background write to tty (POSIX).";
|
||||||
|
case SIGURG: return "SIGURG: Urgent condition on socket (4.2 BSD).";
|
||||||
|
case SIGXCPU: return "SIGXCPU: CPU limit exceeded (4.2 BSD).";
|
||||||
|
case SIGXFSZ: return "SIGXFSZ: File size limit exceeded (4.2 BSD).";
|
||||||
|
case SIGVTALRM: return "SIGVTALRM: Virtual alarm clock (4.2 BSD).";
|
||||||
|
case SIGPROF: return "SIGPROF: Profiling alarm clock (4.2 BSD).";
|
||||||
|
case SIGWINCH: return "SIGWINCH: Window size change (4.3 BSD, Sun).";
|
||||||
|
case SIGIO: return "SIGIO: Pollable event occurred (System V) / I/O now possible (4.2 BSD).";
|
||||||
|
case SIGPWR: return "SIGPWR: Power failure restart (System V).";
|
||||||
|
case SIGSYS: return "SIGSYS: Bad system call.";
|
||||||
|
}
|
||||||
|
static char s[64];
|
||||||
|
sprintf(s, "SIG=%d: Unknown", sig);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crash_handler(int sig)
|
||||||
|
{
|
||||||
|
write_string(2, "Crashing with signal ");
|
||||||
|
write_string(2, signal_name(sig));
|
||||||
|
write_string(2, "\nBacktrace:\n");
|
||||||
|
|
||||||
|
#ifdef ENABLE_LIBUNWIND
|
||||||
|
unw_cursor_t cursor;
|
||||||
|
unw_context_t context;
|
||||||
|
unw_getcontext(&context);
|
||||||
|
unw_init_local(&cursor, &context);
|
||||||
|
|
||||||
|
while (unw_step(&cursor) > 0) {
|
||||||
|
unw_word_t offset;
|
||||||
|
char fname[128];
|
||||||
|
fname[0] = '\0';
|
||||||
|
(void) unw_get_proc_name(&cursor, fname, sizeof(fname), &offset);
|
||||||
|
write_string(2, fname);
|
||||||
|
write_string(2, "\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#ifdef ENABLE_EXECINFO
|
||||||
|
#define MAX_TRACE_SIZE 128
|
||||||
|
void *array[MAX_TRACE_SIZE];
|
||||||
|
size_t size = backtrace(array, MAX_TRACE_SIZE);
|
||||||
|
char **strings = backtrace_symbols(array, size);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
write_string(2, strings[i]);
|
||||||
|
write_string(2, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(strings);
|
||||||
|
#else
|
||||||
|
write_string(2, "Backtrace not supported on this system. Install libunwind or libexecinfo.\n");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
_exit(sig);
|
||||||
|
}
|
||||||
|
|
||||||
void init(int argc, char *argv[])
|
void init(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
// Make stdout/stderr flush after a newline (for some reason they don't even if tint2 is started from a terminal)
|
// Make stdout/stderr flush after a newline (for some reason they don't even if tint2 is started from a terminal)
|
||||||
|
@ -162,11 +263,18 @@ void init(int argc, char *argv[])
|
||||||
signal_pending = 0;
|
signal_pending = 0;
|
||||||
struct sigaction sa = {.sa_handler = signal_handler};
|
struct sigaction sa = {.sa_handler = signal_handler};
|
||||||
struct sigaction sa_chld = {.sa_handler = SIG_DFL, .sa_flags = SA_NOCLDWAIT};
|
struct sigaction sa_chld = {.sa_handler = SIG_DFL, .sa_flags = SA_NOCLDWAIT};
|
||||||
|
struct sigaction sa_crash = {.sa_handler = crash_handler};
|
||||||
sigaction(SIGUSR1, &sa, 0);
|
sigaction(SIGUSR1, &sa, 0);
|
||||||
sigaction(SIGINT, &sa, 0);
|
sigaction(SIGINT, &sa, 0);
|
||||||
sigaction(SIGTERM, &sa, 0);
|
sigaction(SIGTERM, &sa, 0);
|
||||||
sigaction(SIGHUP, &sa, 0);
|
sigaction(SIGHUP, &sa, 0);
|
||||||
sigaction(SIGCHLD, &sa_chld, 0);
|
sigaction(SIGCHLD, &sa_chld, 0);
|
||||||
|
sigaction(SIGSEGV, &sa_crash, 0);
|
||||||
|
sigaction(SIGFPE, &sa_crash, 0);
|
||||||
|
sigaction(SIGPIPE, &sa_crash, 0);
|
||||||
|
sigaction(SIGBUS, &sa_crash, 0);
|
||||||
|
sigaction(SIGABRT, &sa_crash, 0);
|
||||||
|
sigaction(SIGSYS, &sa_crash, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sn_pipe_valid = 0;
|
static int sn_pipe_valid = 0;
|
||||||
|
|
Loading…
Reference in a new issue