[Add] Automagically give backtraces in DEBUG mode.

This commit is contained in:
Allanis 2013-11-26 18:23:50 +00:00
parent 39c7a4ecd5
commit 2a69789a24
4 changed files with 125 additions and 20 deletions

View File

@ -26,19 +26,6 @@ CXML = $(shell xml2-config --cflags)
CTTF = $(shell freetype-config --cflags) CTTF = $(shell freetype-config --cflags)
CGL = CGL =
CFLAGS = $(CLUA) $(CSDL) $(CXML) $(CTTF) $(CGL) $(VERSION) -D$(OS) CFLAGS = $(CLUA) $(CSDL) $(CXML) $(CTTF) $(CGL) $(VERSION) -D$(OS)
ifeq ($(OS),LINUX)
CFLAGS += -D_POSIX_SOURCE
endif
ifdef DEBUG
CFLAGS += -W -Wall -Wextra -Wunused -Wshadow -Wpointer-arith -Wmissing-prototypes \
-Winline -Wcast-align -Wmissing-declarations -fstack-protector \
-fstack-protector-all -g3 -DDEBUG -DLUA_USE_APICHECK -std=c99
ifdef DEBUG_PARANOID
CFLAGS += -DDEBUG_PARANOID
endif
else
CFLAGS += -O2 -funroll-loops -pipe -std=c99
endif
# LDFLAGS. # LDFLAGS.
LDLUA = ../lib/lua/liblua.a LDLUA = ../lib/lua/liblua.a
@ -49,6 +36,31 @@ LDGL = -lGL
LDPNG = -lpng LDPNG = -lpng
LDFLAGS = -lm $(LDLUA) $(LDSDL) $(LDXML) $(LDTTF) $(LDGL) $(LDPNG) LDFLAGS = -lm $(LDLUA) $(LDSDL) $(LDXML) $(LDTTF) $(LDGL) $(LDPNG)
# OS Stuff.
ifeq ($(OS),LINUX)
CFLAGS += -D_POSIX_SOURCE
endif
# Debug stuff.
ifdef DEBUG
CFLAGS += -W -Wall -Wextra -Wunused -Wshadow -Wpointer-arith -Wmissing-prototypes \
-Winline -Wcast-align -Wmissing-declarations -fstack-protector \
-fstack-protector-all -g3 -DDEBUG -DLUA_USE_APICHECK -std=c99
ifdef DEBUG_PARANOID
CFLAGS += -DDEBUG_PARANOID
endif
# Handle OS Debug stuff here.
ifeq ($(OS), LINUX)
LDFLAGS += -rdynamic
endif # Linux.
else # DEBUG
CFLAGS += -O2 -funroll-loops -pipe -std=c99
endif
# This is just for gstat to run some analysis on performance. # This is just for gstat to run some analysis on performance.
ifdef DEBUG ifdef DEBUG
LDFLAGS += -pg LDFLAGS += -pg

View File

@ -10,8 +10,17 @@
*/ */
#include <SDL/SDL.h> #include <SDL/SDL.h>
#include <string.h>
/* Global. */
#include <string.h>
#if defined(LINUX) && !defined(NODEBUG)
#include <signal.h>
#include <execinfo.h>
#include <stdlib.h>
#include <unistd.h>
#endif /* defined(LINUX) && !defined(NODEBUG) */
/* Local. */
#include "lephisto.h" #include "lephisto.h"
#include "conf.h" #include "conf.h"
#include "log.h" #include "log.h"
@ -74,15 +83,17 @@ static void print_SDLversion(void);
static void load_screen(void); static void load_screen(void);
static void load_all(void); static void load_all(void);
static void unload_all(void); static void unload_all(void);
void main_loop(void);
static void display_fps(const double dt); static void display_fps(const double dt);
static void window_caption(void); static void window_caption(void);
static void data_name(void); static void data_name(void);
static void debug_sigInit(void);
/* Update. */ /* Update. */
static void fps_control(void); static void fps_control(void);
static void update_all(void); static void update_all(void);
static void update_routine(double dt); static void update_routine(double dt);
static void render_all(void); static void render_all(void);
/* Misc. */
void main_loop(void); /* dialogue.c */
/** /**
@ -112,6 +123,9 @@ int main(int argc, char** argv) {
/* Initialize SDL for possible warnings. */ /* Initialize SDL for possible warnings. */
SDL_Init(0); SDL_Init(0);
/* Set up debug signal handlers. */
debug_sigInit();
/* Create the home directory if needed. */ /* Create the home directory if needed. */
if(lfile_dirMakeExist(".")) if(lfile_dirMakeExist("."))
WARN("Unable to create lephisto directory '%s'", lfile_basePath()); WARN("Unable to create lephisto directory '%s'", lfile_basePath());
@ -591,3 +605,82 @@ static void print_SDLversion(void) {
WARN("SDL is older than compiled version."); WARN("SDL is older than compiled version.");
} }
#if defined(LINUX) && !defined(NODEBUG)
/**
* @brief Get the string related to the signal code.
* @param sig Signal to which code belongs.
* @param sig_code Signal code to get string of.
* @return String of signal code.
*/
static const char* debug_sigCodeToStr(int sig, int sig_code) {
if(sig == SIGFPE)
switch(sig_code) {
case FPE_INTDIV: return "SIGFPE (integer divide by zero)";
case FPE_INTOVF: return "SIGFPE (integer overflow)";
case FPE_FLTDIV: return "SIGFPE (floating-point divide by zero)";
case FPE_FLTOVF: return "SIGFPE (floating-point overflow)";
case FPE_FLTUND: return "SIGFPE (floating-point underflow)";
case FPE_FLTRES: return "SIGFPE (floating-point inexact result)";
case FPE_FLTINV: return "SIGFPE (floating-point invalid operation)";
case FPE_FLTSUB: return "SIGFPE (subscript out of range)";
default: return "SIGFPE";
}
else if(sig == SIGSEGV)
switch(sig_code) {
case SEGV_MAPERR: return "SIGEGV (address not mapped to object)";
case SEGV_ACCERR: return "SIGEGV (invalid permissions for mapped object)";
default: return "SIGSEGV";
}
/* No suitable code found. */
return strsignal(sig);
}
/**
* @brief Backtrace signal handler for linux.
* @param sig Signal.
* @param info Signal information.
* @param unused Unused.
*/
static void debug_sigHandler(int sig, siginfo_t* info, void* unused) {
(void) sig;
(void) unused;
int i, num;
void* buf[64];
char** symbols;
num = backtrace(buf, 64);
symbols = backtrace_symbols(buf, num);
DEBUG("LEPHISTO recieved %s!",
debug_sigCodeToStr(info->si_signo, info->si_code));
for(i = 0; i < num; i++)
DEBUG(" %s", symbols[i]);
DEBUG("Report this to project maintainer with the backtrace.");
exit(1);
}
#endif /* defined(LINUX) && !defined(DEBUG) */
/**
* @brief Set up the SignalHandler for Linux.
*/
static void debug_sigInit(void) {
#if defined(LINUX) && !defined(NODEBUG)
struct sigaction sa, so;
/* Set up handler. */
sa.sa_handler = NULL;
sa.sa_sigaction = debug_sigHandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
/* Attach signals. */
sigaction(SIGSEGV, &sa, &so);
if(so.sa_handler == SIG_IGN)
DEBUG("Unable to set up SIGSEGV signal handler.");
sigaction(SIGFPE, &sa, &so);
if(so.sa_handler == SIG_IGN)
DEBUG("Unable to set up SIGFPE signal handler.");
#endif /* #if defined(LINUX) && !defined(NODEBUG) */
}

View File

@ -5,7 +5,7 @@
#include "lualib.h" #include "lualib.h"
/* Debug stuff. */ /* Debug stuff. */
#ifdef DEBUG #ifdef NODEBUG
#define LLUA_DEBUG(str, args...) \ #define LLUA_DEBUG(str, args...) \
(fprintf(stdout, "Lua: "str"\n", ## args)) (fprintf(stdout, "Lua: "str"\n", ## args))
@ -19,11 +19,11 @@
LLUA_DEBUG("[%s] Too few arguments (%s:%d)", __func__, __FILE__, __LINE__); \ LLUA_DEBUG("[%s] Too few arguments (%s:%d)", __func__, __FILE__, __LINE__); \
return 0; \ return 0; \
} }
#else /* DEBUG. */ #else /* NODEBUG. */
#define LLUA_DEBUG(str, args...) do {;} while(0) #define LLUA_DEBUG(str, args...) do {;} while(0)
#define LLUA_MIN_ARGS(n) do {;} while(0) #define LLUA_MIN_ARGS(n) do {;} while(0)
#define LLUA_INVALID_PARAMETER() do {;} while(0) #define LLUA_INVALID_PARAMETER() do {;} while(0)
#endif /* DEBUG. */ #endif /* NODEBUG. */
/* Comfortability macros. */ /* Comfortability macros. */
#define luaL_dobuffer(L, b, n, s) \ #define luaL_dobuffer(L, b, n, s) \

View File

@ -9,9 +9,9 @@
#define LOG(str, args...)(fprintf(stdout, str"\n", ## args)) #define LOG(str, args...)(fprintf(stdout, str"\n", ## args))
#ifdef DEBUG_PARANOID /* Will cause WARN's to blow up. */ #ifdef DEBUG_PARANOID /* Will cause WARN's to blow up. */
#define WARN(str, args...)(fprintf(stderr, "Warning: "str"\n", ## args), assert(0)) #define WARN(str, args...)(fprintf(stderr, "Warning: [%s] "str"\n", __func__, ## args), assert(0))
#else #else
#define WARN(str, args...)(fprintf(stderr, "Warning: "str"\n", ## args)) #define WARN(str, args...)(fprintf(stderr, "Warning: [%s] "str"\n", __func__, ## args))
#endif #endif
#define ERR(str, args...) (fprintf(stderr, "ERROR %s:%d: [%s] "str"\n", \ #define ERR(str, args...) (fprintf(stderr, "ERROR %s:%d: [%s] "str"\n", \