mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +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)
|
||||
|
||||
# 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;
|
||||
@@ -121,14 +124,14 @@ static void my_exit(int exit_code)
|
||||
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 */
|
||||
|
Reference in New Issue
Block a user