diff options
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/my_addr_resolve.c | 68 | ||||
-rw-r--r-- | mysys/stacktrace.c | 45 |
2 files changed, 86 insertions, 27 deletions
diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index 7590d576a7c..ff15558ddd4 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -191,7 +191,9 @@ int start_addr2line_fork(const char *binary_path) return 0; } -int my_addr_resolve(void *ptr, my_addr_loc *loc) +static int first_error= 0; + +static int addr_resolve(void *ptr, my_addr_loc *loc) { char input[32]; size_t len; @@ -206,29 +208,13 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) int filename_start = -1; int line_number_start = -1; - Dl_info info; - void *offset; - - if (!dladdr(ptr, &info)) - return 1; - - if (strcmp(addr2line_binary, info.dli_fname)) - { - /* We use dli_fname in case the path is longer than the length of our static - string. We don't want to allocate anything dynamicaly here as we are in - a "crashed" state. */ - if (start_addr2line_fork(info.dli_fname)) - { - addr2line_binary[0] = '\0'; - return 2; - } - /* Save result for future comparisons. */ - strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); - } - offset = info.dli_fbase; - len= my_snprintf(input, sizeof(input), "%08x\n", (ulonglong)(ptr - offset)); + len= my_snprintf(input, sizeof(input), "%p\n", ptr); if (write(in[1], input, len) <= 0) + { + if (!first_error++) + fputs("Printing to addr2line failed\n", stderr); return 3; + } FD_ZERO(&set); FD_SET(out[0], &set); @@ -278,7 +264,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) loc->line= atoi(output + line_number_start); /* Addr2line was unable to extract any meaningful information. */ - if (strcmp(loc->file, "??") == 0) + if (strcmp(loc->file, "??") == 0 && loc->func[0] == '?') return 6; loc->file= strip_path(loc->file); @@ -286,6 +272,42 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) return 0; } + +int my_addr_resolve(void *ptr, my_addr_loc *loc) +{ + Dl_info info; + int error; + + if (!dladdr(ptr, &info)) + return 1; + + if (strcmp(addr2line_binary, info.dli_fname)) + { + /* + We use dli_fname in case the path is longer than the length of + our static string. We don't want to allocate anything + dynamicaly here as we are in a "crashed" state. + */ + if (start_addr2line_fork(info.dli_fname)) + { + if (!first_error++) + fputs("Can't start addr2line\n", stderr); + addr2line_binary[0] = '\0'; + return 2; + } + /* Save result for future comparisons. */ + strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); + } + if (!(error= addr_resolve(ptr, loc))) + return 0; +#ifdef EXTRA_RESOLVE + if (!(error= addr_resolve((void*) (ptr - info.dli_fbase), loc))) + return 0; +#endif + return error; +} + + const char *my_addr_resolve_init() { return 0; diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c index 2274c505195..19dcdf11dd5 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -14,12 +14,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ -#include <my_global.h> +#include "mysys_priv.h" #include <my_stacktrace.h> #ifndef __WIN__ #include <signal.h> -#include <my_pthread.h> #include <m_string.h> #ifdef HAVE_STACKTRACE #include <unistd.h> @@ -42,11 +41,49 @@ static char *heap_start; extern char *__bss_start; #endif -void my_init_stacktrace() +/** + Default handler for printing stacktrace +*/ + +static sig_handler default_handle_fatal_signal(int sig) +{ + my_safe_printf_stderr("%s: Got signal %d. Attempting backtrace\n", + my_progname_short, sig); + my_print_stacktrace(0,0,1); +#ifndef __WIN__ + signal(sig, SIG_DFL); + kill(getpid(), sig); +#endif /* __WIN__ */ + return; +} + + +/** + Initialize priting off stacktrace at signal + + @param setup_handlers 0 only initialize variables + 1 setup signal handlers for stacktrace printing +*/ + +void my_init_stacktrace(int setup_handlers) { #if(defined HAVE_BSS_START) && !(defined __linux__) heap_start = (char*) &__bss_start; #endif + if (setup_handlers) + { + struct sigaction sa; + sa.sa_flags = SA_RESETHAND | SA_NODEFER; + sigemptyset(&sa.sa_mask); + sa.sa_handler= default_handle_fatal_signal; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGABRT, &sa, NULL); +#ifdef SIGBUS + sigaction(SIGBUS, &sa, NULL); +#endif + sigaction(SIGILL, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); + } } #ifdef __linux__ @@ -510,7 +547,7 @@ static EXCEPTION_POINTERS *exception_ptrs; #define MODULE64_SIZE_WINXP 576 #define STACKWALK_MAX_FRAMES 64 -void my_init_stacktrace() +void my_init_stacktrace(int setup_handlers __attribute__((unused))) { } |