Commit ebfe8c4e authored by Monty's avatar Monty

Make it trivial to get stack traces from external programs.

To get a stacktrace in a program like aria_chk, one only have to do:

#include <my_stacktrace.h>

call my_init_stacktrace(1) in main().
parent ab38b751
...@@ -16,6 +16,11 @@ ...@@ -16,6 +16,11 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7) CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7)
# Remove the following comment if you don't want to have striped binaries
# in RPM's:
#set(CPACK_RPM_SPEC_MORE_DEFINE "%define __spec_install_post /bin/true")
IF(POLICY CMP0022) IF(POLICY CMP0022)
CMAKE_POLICY(SET CMP0022 NEW) CMAKE_POLICY(SET CMP0022 NEW)
ENDIF() ENDIF()
......
...@@ -9116,7 +9116,7 @@ static void init_signal_handling(void) ...@@ -9116,7 +9116,7 @@ static void init_signal_handling(void)
DBUG_ENTER("init_signal_handling"); DBUG_ENTER("init_signal_handling");
#ifdef HAVE_STACKTRACE #ifdef HAVE_STACKTRACE
my_init_stacktrace(); my_init_stacktrace(0);
#endif #endif
sa.sa_flags = SA_RESETHAND | SA_NODEFER; sa.sa_flags = SA_RESETHAND | SA_NODEFER;
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
C_MODE_START C_MODE_START
#if defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE) #if defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE)
void my_init_stacktrace(); void my_init_stacktrace(int setup_handlers);
void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack, void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack,
my_bool silent); my_bool silent);
int my_safe_print_str(const char* val, size_t max_len); int my_safe_print_str(const char* val, size_t max_len);
...@@ -53,7 +53,7 @@ char *my_demangle(const char *mangled_name, int *status); ...@@ -53,7 +53,7 @@ char *my_demangle(const char *mangled_name, int *status);
void my_set_exception_pointers(EXCEPTION_POINTERS *ep); void my_set_exception_pointers(EXCEPTION_POINTERS *ep);
#endif /* __WIN__ */ #endif /* __WIN__ */
#else #else
#define my_init_stacktrace() do { } while(0) #define my_init_stacktrace(A) do { } while(0)
#endif /* ! (defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE)) */ #endif /* ! (defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE)) */
#ifndef _WIN32 #ifndef _WIN32
......
...@@ -115,7 +115,14 @@ check table t5; ...@@ -115,7 +115,14 @@ check table t5;
# Check that if we zerofill with aria_chk, we should not get any warnings when # Check that if we zerofill with aria_chk, we should not get any warnings when
# accessing the table # accessing the table
--error 0,1,11,139
--exec $MARIA_CHK --ignore-control-file --zerofill $MYSQLD_DATADIR/mysqltest/t6 >$MYSQLTEST_VARDIR/tmp/autozerofill.txt 2>&1 --exec $MARIA_CHK --ignore-control-file --zerofill $MYSQLD_DATADIR/mysqltest/t6 >$MYSQLTEST_VARDIR/tmp/autozerofill.txt 2>&1
if ($sys_errno != 0)
{
--cat_file $MYSQLTEST_VARDIR/tmp/autozerofill.txt
--die
}
select * from t6; select * from t6;
check table t6; check table t6;
......
...@@ -191,7 +191,9 @@ int start_addr2line_fork(const char *binary_path) ...@@ -191,7 +191,9 @@ int start_addr2line_fork(const char *binary_path)
return 0; 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]; char input[32];
size_t len; size_t len;
...@@ -206,29 +208,13 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) ...@@ -206,29 +208,13 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc)
int filename_start = -1; int filename_start = -1;
int line_number_start = -1; int line_number_start = -1;
Dl_info info; len= my_snprintf(input, sizeof(input), "%p\n", ptr);
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));
if (write(in[1], input, len) <= 0) if (write(in[1], input, len) <= 0)
{
if (!first_error++)
fputs("Printing to addr2line failed\n", stderr);
return 3; return 3;
}
FD_ZERO(&set); FD_ZERO(&set);
FD_SET(out[0], &set); FD_SET(out[0], &set);
...@@ -278,7 +264,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) ...@@ -278,7 +264,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc)
loc->line= atoi(output + line_number_start); loc->line= atoi(output + line_number_start);
/* Addr2line was unable to extract any meaningful information. */ /* Addr2line was unable to extract any meaningful information. */
if (strcmp(loc->file, "??") == 0) if (strcmp(loc->file, "??") == 0 && loc->func[0] == '?')
return 6; return 6;
loc->file= strip_path(loc->file); loc->file= strip_path(loc->file);
...@@ -286,6 +272,42 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) ...@@ -286,6 +272,42 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc)
return 0; 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() const char *my_addr_resolve_init()
{ {
return 0; return 0;
......
...@@ -14,12 +14,11 @@ ...@@ -14,12 +14,11 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include <my_global.h> #include "mysys_priv.h"
#include <my_stacktrace.h> #include <my_stacktrace.h>
#ifndef __WIN__ #ifndef __WIN__
#include <signal.h> #include <signal.h>
#include <my_pthread.h>
#include <m_string.h> #include <m_string.h>
#ifdef HAVE_STACKTRACE #ifdef HAVE_STACKTRACE
#include <unistd.h> #include <unistd.h>
...@@ -42,11 +41,49 @@ static char *heap_start; ...@@ -42,11 +41,49 @@ static char *heap_start;
extern char *__bss_start; extern char *__bss_start;
#endif #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__) #if(defined HAVE_BSS_START) && !(defined __linux__)
heap_start = (char*) &__bss_start; heap_start = (char*) &__bss_start;
#endif #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__ #ifdef __linux__
...@@ -510,7 +547,7 @@ static EXCEPTION_POINTERS *exception_ptrs; ...@@ -510,7 +547,7 @@ static EXCEPTION_POINTERS *exception_ptrs;
#define MODULE64_SIZE_WINXP 576 #define MODULE64_SIZE_WINXP 576
#define STACKWALK_MAX_FRAMES 64 #define STACKWALK_MAX_FRAMES 64
void my_init_stacktrace() void my_init_stacktrace(int setup_handlers __attribute__((unused)))
{ {
} }
......
...@@ -2995,7 +2995,7 @@ void init_signals(void) ...@@ -2995,7 +2995,7 @@ void init_signals(void)
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL); sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
my_init_stacktrace(); my_init_stacktrace(0);
#if defined(__amiga__) #if defined(__amiga__)
sa.sa_handler=(void(*)())handle_fatal_signal; sa.sa_handler=(void(*)())handle_fatal_signal;
#else #else
......
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
#ifdef HAVE_SYS_MMAN_H #ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif
/* Remove next line if you want aria_chk to produce a stack trace */
#undef HAVE_BACKTRACE
#include <my_stacktrace.h>
static uint decode_bits; static uint decode_bits;
static char **default_argv; static char **default_argv;
...@@ -121,14 +124,14 @@ static void my_exit(int exit_code) ...@@ -121,14 +124,14 @@ static void my_exit(int exit_code)
exit(exit_code); exit(exit_code);
} }
/* Main program */
/* Main program */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int error; int error;
MY_INIT(argv[0]); MY_INIT(argv[0]);
my_init_stacktrace(1);
default_log_dir= opt_log_dir= maria_data_root= (char *)"."; default_log_dir= opt_log_dir= maria_data_root= (char *)".";
maria_chk_init(&check_param); maria_chk_init(&check_param);
check_param.opt_lock_memory= 1; /* Lock memory if possible */ check_param.opt_lock_memory= 1; /* Lock memory if possible */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment