mirror of
https://github.com/MariaDB/server.git
synced 2025-08-09 22:24:09 +03:00
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().
This commit is contained in:
@@ -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)
|
|||||||
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 @@
|
|||||||
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);
|
|||||||
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;
|
|||||||
|
|
||||||
# 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
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;
|
|||||||
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;
|
|||||||
#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)
|
|||||||
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 @@
|
|||||||
#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;
|
||||||
@@ -120,15 +123,15 @@ static void my_exit(int exit_code)
|
|||||||
MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
|
MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
|
||||||
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 */
|
||||||
|
Reference in New Issue
Block a user