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 @@
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)
CMAKE_POLICY(SET CMP0022 NEW)
ENDIF()
......
......@@ -9116,7 +9116,7 @@ static void init_signal_handling(void)
DBUG_ENTER("init_signal_handling");
#ifdef HAVE_STACKTRACE
my_init_stacktrace();
my_init_stacktrace(0);
#endif
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
......
......@@ -41,7 +41,7 @@
C_MODE_START
#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,
my_bool silent);
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);
void my_set_exception_pointers(EXCEPTION_POINTERS *ep);
#endif /* __WIN__ */
#else
#define my_init_stacktrace() do { } while(0)
#define my_init_stacktrace(A) do { } while(0)
#endif /* ! (defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE)) */
#ifndef _WIN32
......
......@@ -115,7 +115,14 @@ check table t5;
# Check that if we zerofill with aria_chk, we should not get any warnings when
# 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
if ($sys_errno != 0)
{
--cat_file $MYSQLTEST_VARDIR/tmp/autozerofill.txt
--die
}
select * from t6;
check table t6;
......
......@@ -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;
......
......@@ -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-1301 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)))
{
}
......
......@@ -2995,7 +2995,7 @@ void init_signals(void)
sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
my_init_stacktrace();
my_init_stacktrace(0);
#if defined(__amiga__)
sa.sa_handler=(void(*)())handle_fatal_signal;
#else
......
......@@ -26,6 +26,9 @@
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#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 char **default_argv;
......@@ -120,15 +123,15 @@ static void my_exit(int exit_code)
MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
exit(exit_code);
}
/* Main program */
/* Main program */
int main(int argc, char **argv)
{
int error;
MY_INIT(argv[0]);
my_init_stacktrace(1);
default_log_dir= opt_log_dir= maria_data_root= (char *)".";
maria_chk_init(&check_param);
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