From fcaaee631792b51ce7ea12db1d5f5c2019d0fa3b Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 19 Jun 2008 11:02:32 -0300 Subject: [PATCH] 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. --- client/mysqltest.c | 26 ++++++-- configure.in | 11 ++++ include/my_stacktrace.h | 5 ++ mysys/stacktrace.c | 134 ++++++++++++++++++++-------------------- sql/mysqld.cc | 2 + 5 files changed, 107 insertions(+), 71 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 #endif +#include #include #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,7 +63,68 @@ void my_safe_print_str(const char* name, const char* val, int max_len) fputc('\n', stderr); } -#ifdef TARGET_OS_LINUX +#if HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD) + +#if BACKTRACE_DEMANGLE + +char __attribute__ ((weak)) *my_demangle(const char *mangled_name, int *status) +{ + return NULL; +} + +static void my_demangle_symbols(char **addrs, int n) +{ + int status, i; + char *begin, *end, *demangled; + + for (i= 0; i < n; i++) + { + demangled= NULL; + begin= strchr(addrs[i], '('); + end= begin ? strchr(begin, '+') : NULL; + + if (begin && end) + { + *begin++= *end++= '\0'; + demangled= my_demangle(begin, &status); + if (!demangled || status) + { + demangled= NULL; + begin[-1]= '('; + end[-1]= '+'; + } + } + + if (demangled) + fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end); + else + fprintf(stderr, "%s\n", addrs[i]); + } +} + +#endif /* BACKTRACE_DEMANGLE */ + +void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack) +{ + void *addrs[128]; + char **strings= NULL; + int n = backtrace(addrs, array_elements(addrs)); +#if BACKTRACE_DEMANGLE + if ((strings= backtrace_symbols(addrs, n))) + { + my_demangle_symbols(strings, n); + free(strings); + } +#endif +#if HAVE_BACKTRACE_SYMBOLS_FD + if (!strings) + { + backtrace_symbols_fd(addrs, n, fileno(stderr)); + } +#endif +} + +#elif defined(TARGET_OS_LINUX) #ifdef __i386__ #define SIGRETURN_FRAME_OFFSET 17 @@ -108,74 +174,8 @@ inline uint32* find_prev_pc(uint32* pc, uchar** fp) } #endif /* defined(__alpha__) && defined(__GNUC__) */ -#if BACKTRACE_DEMANGLE - -char __attribute__ ((weak)) *my_demangle(const char *mangled_name, int *status) -{ - return NULL; -} - -static void my_demangle_symbols(char **addrs, int n) -{ - int status, i; - char *begin, *end, *demangled; - - for (i= 0; i < n; i++) - { - demangled= NULL; - begin= strchr(addrs[i], '('); - end= begin ? strchr(begin, '+') : NULL; - - if (begin && end) - { - *begin++= *end++= '\0'; - demangled= my_demangle(begin, &status); - if (!demangled || status) - { - demangled= NULL; - begin[-1]= '('; - end[-1]= '+'; - } - } - - if (demangled) - fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end); - else - fprintf(stderr, "%s\n", addrs[i]); - } -} -#endif - - -#if HAVE_BACKTRACE -static void backtrace_current_thread(void) -{ - void *addrs[128]; - char **strings= NULL; - int n = backtrace(addrs, array_elements(addrs)); -#if BACKTRACE_DEMANGLE - if ((strings= backtrace_symbols(addrs, n))) - { - my_demangle_symbols(strings, n); - free(strings); - } -#endif -#if HAVE_BACKTRACE_SYMBOLS_FD - if (!strings) - { - backtrace_symbols_fd(addrs, n, fileno(stderr)); - } -#endif -} -#endif - - 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