diff options
author | Davi Arnaut <davi@mysql.com> | 2008-06-19 11:02:32 -0300 |
---|---|---|
committer | Davi Arnaut <davi@mysql.com> | 2008-06-19 11:02:32 -0300 |
commit | fcaaee631792b51ce7ea12db1d5f5c2019d0fa3b (patch) | |
tree | a27f81ac24a83b96d235ee7489aefe3223a88867 | |
parent | fb8f32d0774876f79f7e3d9aa714c0ecb67adaca (diff) | |
download | mariadb-git-fcaaee631792b51ce7ea12db1d5f5c2019d0fa3b.tar.gz |
Bug#37003 Tests sporadically crashes with embedded server
Another problem is that the backtrace facility wasn't being
enabled for non-Linux targets even if the target OS has the
backtrace functions. Also, the stacktrace functions inside
mysqltest were being used without proper checks for their
presence in the build.
client/mysqltest.c:
Only use stacktrace functions if they are available.
configure.in:
Check if the compiler defines __bss_start
include/my_stacktrace.h:
Enable stacktrace if system has backtrace functions.
mysys/stacktrace.c:
Use backtrace functions if the system supports it.
sql/mysqld.cc:
Only use stacktrace functions if they are available.
-rw-r--r-- | client/mysqltest.c | 26 | ||||
-rw-r--r-- | configure.in | 11 | ||||
-rw-r--r-- | include/my_stacktrace.h | 5 | ||||
-rw-r--r-- | mysys/stacktrace.c | 112 | ||||
-rw-r--r-- | sql/mysqld.cc | 2 |
5 files changed, 96 insertions, 60 deletions
diff --git a/client/mysqltest.c b/client/mysqltest.c index 5cc0951cdf5..f5a5c05b236 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -48,6 +48,7 @@ #ifdef __WIN__ #include <direct.h> #endif +#include <signal.h> #include <my_stacktrace.h> #ifdef __WIN__ @@ -6847,12 +6848,12 @@ void mark_progress(struct st_command* command __attribute__((unused)), } +#ifdef HAVE_STACKTRACE -static sig_handler dump_backtrace(int sig) +static void dump_backtrace(void) { struct st_connection *conn= cur_con; - fprintf(stderr, "mysqltest got " SIGNAL_FMT "\n", sig); my_safe_print_str("read_command_buf", read_command_buf, sizeof(read_command_buf)); if (conn) @@ -6866,6 +6867,21 @@ static sig_handler dump_backtrace(int sig) my_print_stacktrace(NULL, my_thread_stack_size); } +#else + +static void dump_backtrace(void) +{ + fputs("Backtrace not available.\n", stderr); +} + +#endif + +static sig_handler signal_handler(int sig) +{ + fprintf(stderr, "mysqltest got " SIGNAL_FMT "\n", sig); + dump_backtrace(); +} + #ifdef __WIN__ LONG WINAPI exception_filter(EXCEPTION_POINTERS *exp) @@ -6873,7 +6889,7 @@ LONG WINAPI exception_filter(EXCEPTION_POINTERS *exp) __try { my_set_exception_pointers(exp); - dump_backtrace(exp->ExceptionRecord->ExceptionCode); + signal_handler(exp->ExceptionRecord->ExceptionCode); } __except(EXCEPTION_EXECUTE_HANDLER) { @@ -6910,13 +6926,15 @@ static void init_signal_handling(void) struct sigaction sa; DBUG_ENTER("init_signal_handling"); +#ifdef HAVE_STACKTRACE my_init_stacktrace(); +#endif sa.sa_flags = SA_RESETHAND | SA_NODEFER; sigemptyset(&sa.sa_mask); sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL); - sa.sa_handler= dump_backtrace; + sa.sa_handler= signal_handler; sigaction(SIGSEGV, &sa, NULL); sigaction(SIGABRT, &sa, NULL); diff --git a/configure.in b/configure.in index 033cabf1875..54817c3c253 100644 --- a/configure.in +++ b/configure.in @@ -2351,6 +2351,17 @@ if test "x$mysql_cv_weak_symbol" = xyes; then [Define to 1 if compiler supports weak symbol attribute.]) fi +AC_CACHE_CHECK([whether __bss_start is defined], mysql_cv_bss_start, +[AC_TRY_LINK([],[ + extern char *__bss_start; + return __bss_start ? 1 : 0; +], [mysql_cv_bss_start=yes], [mysql_cv_bss_start=no])]) + +if test "x$mysql_cv_bss_start" = xyes; then + AC_DEFINE(HAVE_BSS_START, 1, + [Define to 1 if compiler defines __bss_start.]) +fi + AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_CHECK_HEADERS(cxxabi.h) diff --git a/include/my_stacktrace.h b/include/my_stacktrace.h index 3d51ba92ee1..e7ce42c1f4f 100644 --- a/include/my_stacktrace.h +++ b/include/my_stacktrace.h @@ -27,6 +27,11 @@ #define HAVE_STACKTRACE 1 #endif +#if HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD) +#undef HAVE_STACKTRACE +#define HAVE_STACKTRACE 1 +#endif + #if !defined(__NETWARE__) #define HAVE_WRITE_CORE #endif diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c index 7466dcb416e..9ae3d88ef50 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -34,11 +34,16 @@ #define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end) static char *heap_start; + +#ifdef HAVE_BSS_START extern char *__bss_start; +#endif void my_init_stacktrace() { +#ifdef HAVE_BSS_START heap_start = (char*) &__bss_start; +#endif } void my_safe_print_str(const char* name, const char* val, int max_len) @@ -58,55 +63,7 @@ void my_safe_print_str(const char* name, const char* val, int max_len) fputc('\n', stderr); } -#ifdef TARGET_OS_LINUX - -#ifdef __i386__ -#define SIGRETURN_FRAME_OFFSET 17 -#endif - -#ifdef __x86_64__ -#define SIGRETURN_FRAME_OFFSET 23 -#endif - -#if defined(__alpha__) && defined(__GNUC__) -/* - The only way to backtrace without a symbol table on alpha - is to find stq fp,N(sp), and the first byte - of the instruction opcode will give us the value of N. From this - we can find where the old value of fp is stored -*/ - -#define MAX_INSTR_IN_FUNC 10000 - -inline uchar** find_prev_fp(uint32* pc, uchar** fp) -{ - int i; - for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc) - { - uchar* p = (uchar*)pc; - if (p[2] == 222 && p[3] == 35) - { - return (uchar**)((uchar*)fp - *(short int*)p); - } - } - return 0; -} - -inline uint32* find_prev_pc(uint32* pc, uchar** fp) -{ - int i; - for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc) - { - char* p = (char*)pc; - if (p[1] == 0 && p[2] == 94 && p[3] == -73) - { - uint32* prev_pc = (uint32*)*((fp+p[0]/sizeof(fp))); - return prev_pc; - } - } - return 0; -} -#endif /* defined(__alpha__) && defined(__GNUC__) */ +#if HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD) #if BACKTRACE_DEMANGLE @@ -144,11 +101,10 @@ static void my_demangle_symbols(char **addrs, int n) fprintf(stderr, "%s\n", addrs[i]); } } -#endif +#endif /* BACKTRACE_DEMANGLE */ -#if HAVE_BACKTRACE -static void backtrace_current_thread(void) +void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack) { void *addrs[128]; char **strings= NULL; @@ -167,15 +123,59 @@ static void backtrace_current_thread(void) } #endif } + +#elif defined(TARGET_OS_LINUX) + +#ifdef __i386__ +#define SIGRETURN_FRAME_OFFSET 17 #endif +#ifdef __x86_64__ +#define SIGRETURN_FRAME_OFFSET 23 +#endif + +#if defined(__alpha__) && defined(__GNUC__) +/* + The only way to backtrace without a symbol table on alpha + is to find stq fp,N(sp), and the first byte + of the instruction opcode will give us the value of N. From this + we can find where the old value of fp is stored +*/ + +#define MAX_INSTR_IN_FUNC 10000 + +inline uchar** find_prev_fp(uint32* pc, uchar** fp) +{ + int i; + for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc) + { + uchar* p = (uchar*)pc; + if (p[2] == 222 && p[3] == 35) + { + return (uchar**)((uchar*)fp - *(short int*)p); + } + } + return 0; +} + +inline uint32* find_prev_pc(uint32* pc, uchar** fp) +{ + int i; + for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc) + { + char* p = (char*)pc; + if (p[1] == 0 && p[2] == 94 && p[3] == -73) + { + uint32* prev_pc = (uint32*)*((fp+p[0]/sizeof(fp))); + return prev_pc; + } + } + return 0; +} +#endif /* defined(__alpha__) && defined(__GNUC__) */ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack) { -#if HAVE_BACKTRACE - backtrace_current_thread(); - return; -#endif uchar** fp; uint frame_count = 0, sigreturn_frame_count; #if defined(__alpha__) && defined(__GNUC__) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0bbd0abe9b9..d223b50c99f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2538,7 +2538,9 @@ static void init_signals(void) sigemptyset(&sa.sa_mask); sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL); +#ifdef HAVE_STACKTRACE my_init_stacktrace(); +#endif #if defined(__amiga__) sa.sa_handler=(void(*)())handle_segfault; #else |