From d9831ae5329d6916667ee9beb885c3e4c35c4018 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Feb 2008 19:58:06 -0200 Subject: [PATCH] Bug#31891 Meaningful stack trace On crashes generate a user-friendly resolved and demangled stack trace when libc provides the necessary functions (newer libc on i386, x86_64, powerpc, ia64, alpha and s390). Otherwise print a numeric stack trace as before, relying on resolve_stack_dump utility. configure.in: Add check for backtrace headers, backtrace functions and if __cxa_demangle (libstdc++) is available at link time. sql/mysqld.cc: Print the value of the THD::killed variable when dumping. In some circumstances knowing if the thread was killed makes debugging easier. sql/stacktrace.c: Use the glibc backtrace function when available and demangle C++ function names if the __cxa_demangle function is available. sql/stacktrace.h: Locally export and wrap in C linkage the C++ function __cxa_demangle if available. --- configure.in | 21 +++++++++++++--- sql/mysqld.cc | 29 ++++++++++++++++++++++ sql/stacktrace.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ sql/stacktrace.h | 8 ++++++ 4 files changed, 119 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 1346a87c35a..2e623aacaf7 100644 --- a/configure.in +++ b/configure.in @@ -813,8 +813,8 @@ AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.h \ sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \ unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \ sys/ioctl.h malloc.h sys/malloc.h sys/ipc.h sys/shm.h linux/config.h \ - sys/prctl.h \ - sys/resource.h sys/param.h port.h ieeefp.h) + sys/prctl.h sys/resource.h sys/param.h port.h ieeefp.h \ + execinfo.h) AC_CHECK_HEADERS([xfs/xfs.h]) @@ -2041,7 +2041,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bsearch bzero \ sighold sigset sigthreadmask port_create sleep \ snprintf socket stpcpy strcasecmp strerror strsignal strnlen strpbrk strstr \ strtol strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr \ - posix_fallocate) + posix_fallocate backtrace backtrace_symbols backtrace_symbols_fd) # # @@ -2331,6 +2331,21 @@ then fi AC_MSG_RESULT("$netinet_inc") +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +AC_CHECK_HEADERS(cxxabi.h) +AC_CACHE_CHECK([checking for abi::__cxa_demangle], mysql_cv_cxa_demangle, +[AC_TRY_LINK([#include ], [ + char *foo= 0; int bar= 0; + foo= abi::__cxa_demangle(foo, foo, 0, &bar); +], [mysql_cv_cxa_demangle=yes], [mysql_cv_cxa_demangle=no])]) +AC_LANG_RESTORE + +if test "x$mysql_cv_cxa_demangle" = xyes; then + AC_DEFINE(HAVE_ABI_CXA_DEMANGLE, 1, + [Define to 1 if you have the `abi::__cxa_demangle' function.]) +fi + #-------------------------------------------------------------------- # Check for requested features #-------------------------------------------------------------------- diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9dc77fb8356..84f7620962e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2182,6 +2182,16 @@ static void check_data_home(const char *path) #define UNSAFE_DEFAULT_LINUX_THREADS 200 #endif + +#if BACKTRACE_DEMANGLE +#include +extern "C" char *my_demangle(const char *mangled_name, int *status) +{ + return abi::__cxa_demangle(mangled_name, NULL, NULL, status); +} +#endif + + extern "C" sig_handler handle_segfault(int sig) { time_t curr_time; @@ -2253,10 +2263,29 @@ the thread stack. Please read http://dev.mysql.com/doc/mysql/en/linux.html\n\n", } if (thd) { + const char *kreason= "UNKNOWN"; + switch (thd->killed) { + case THD::NOT_KILLED: + kreason= "NOT_KILLED"; + break; + case THD::KILL_BAD_DATA: + kreason= "KILL_BAD_DATA"; + break; + case THD::KILL_CONNECTION: + kreason= "KILL_CONNECTION"; + break; + case THD::KILL_QUERY: + kreason= "KILL_QUERY"; + break; + case THD::KILLED_NO_VALUE: + kreason= "KILLED_NO_VALUE"; + break; + } fprintf(stderr, "Trying to get some variables.\n\ Some pointers may be invalid and cause the dump to abort...\n"); safe_print_str("thd->query", thd->query, 1024); fprintf(stderr, "thd->thread_id=%lu\n", (ulong) thd->thread_id); + fprintf(stderr, "thd->killed=%s\n", kreason); } fprintf(stderr, "\ The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains\n\ diff --git a/sql/stacktrace.c b/sql/stacktrace.c index b1267e20774..3d718dfd9d2 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -17,11 +17,16 @@ #include "stacktrace.h" #include #include +#include #ifdef HAVE_STACKTRACE #include #include +#if HAVE_EXECINFO_H +#include +#endif + #define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end) char *heap_start; @@ -93,9 +98,68 @@ inline uint32* find_prev_pc(uint32* pc, uchar** fp) } #endif /* defined(__alpha__) && defined(__GNUC__) */ +#if BACKTRACE_DEMANGLE +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 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/stacktrace.h b/sql/stacktrace.h index 1a0b80c88d3..96c09a21ad6 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -17,6 +17,14 @@ extern "C" { #endif +#if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS && HAVE_CXXABI_H && HAVE_ABI_CXA_DEMANGLE +#define BACKTRACE_DEMANGLE 1 +#endif + +#if BACKTRACE_DEMANGLE +char *my_demangle(const char *mangled_name, int *status); +#endif + #ifdef TARGET_OS_LINUX #if defined(HAVE_STACKTRACE) || (defined (__x86_64__) || defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) #undef HAVE_STACKTRACE