mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
add safemalloc back
... but differently client/mysqltest.cc: my_safe_print_str() don't append \n anymore dbug/dbug.c: restore safemalloc as a part of dbug suite dbug/user.r: restore 'S' flag documentation include/my_dbug.h: restore safemalloc as a part of dbug suite include/my_sys.h: move valgrind defines to a dedicated header mysys/my_malloc.c: use new safemalloc mysys/stacktrace.c: don't append \n. let the calller do it, if needed sql/mysqld.cc: my_safe_print_str() don't append \n anymore
This commit is contained in:
@ -8173,14 +8173,17 @@ static void dump_backtrace(void)
|
||||
|
||||
fprintf(stderr, "read_command_buf (%p): ", read_command_buf);
|
||||
my_safe_print_str(read_command_buf, sizeof(read_command_buf));
|
||||
fputc('\n', stderr);
|
||||
|
||||
if (conn)
|
||||
{
|
||||
fprintf(stderr, "conn->name (%p): ", conn->name);
|
||||
my_safe_print_str(conn->name, conn->name_len);
|
||||
fputc('\n', stderr);
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
fprintf(stderr, "conn->cur_query (%p): ", conn->cur_query);
|
||||
my_safe_print_str(conn->cur_query, conn->cur_query_len);
|
||||
fputc('\n', stderr);
|
||||
#endif
|
||||
}
|
||||
fputs("Attempting backtrace...\n", stderr);
|
||||
|
371
dbug/dbug.c
371
dbug/dbug.c
@ -96,8 +96,8 @@
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
|
||||
#include <my_valgrind.h> /* TRASH */
|
||||
#include <my_stacktrace.h> /* my_safe_print_str */
|
||||
|
||||
/*
|
||||
* Manifest constants which may be "tuned" if desired.
|
||||
@ -126,6 +126,7 @@
|
||||
#define TIMESTAMP_ON (1 << 9) /* timestamp every line of output */
|
||||
#define FLUSH_ON_WRITE (1 << 10) /* Flush on every write */
|
||||
#define OPEN_APPEND (1 << 11) /* Open for append */
|
||||
#define SANITY_CHECK_ON (1 << 12) /* Check memory on every DBUG_ENTER/RETURN */
|
||||
#define TRACE_ON ((uint)1 << 31) /* Trace enabled. MUST be the highest bit!*/
|
||||
|
||||
#define TRACING (cs->stack->flags & TRACE_ON)
|
||||
@ -204,6 +205,8 @@ static BOOLEAN init_done= FALSE; /* Set to TRUE when initialization done */
|
||||
static struct settings init_settings;
|
||||
static const char *db_process= 0;/* Pointer to process name; argv[0] */
|
||||
my_bool _dbug_on_= TRUE; /* FALSE if no debugging at all */
|
||||
static const char *unknown_func= "?func";
|
||||
static const char *unknown_file= "?file";
|
||||
|
||||
typedef struct _db_code_state_ {
|
||||
const char *process; /* Pointer to process name; usually argv[0] */
|
||||
@ -284,6 +287,8 @@ static void DbugExit(const char *why);
|
||||
static const char *DbugStrTok(const char *s);
|
||||
static void DbugVfprintf(FILE *stream, const char* format, va_list args);
|
||||
|
||||
static void DbugErr(CODE_STATE *, uint, const char* format, ...);
|
||||
|
||||
/*
|
||||
* Miscellaneous printf format strings.
|
||||
*/
|
||||
@ -306,6 +311,8 @@ static void DbugVfprintf(FILE *stream, const char* format, va_list args);
|
||||
#define WRITABLE(pathname) (access(pathname, W_OK) == 0)
|
||||
#endif
|
||||
|
||||
static int sf_sanity();
|
||||
static void sf_terminate();
|
||||
|
||||
/*
|
||||
** Macros to allow dbugging with threads
|
||||
@ -314,6 +321,9 @@ static void DbugVfprintf(FILE *stream, const char* format, va_list args);
|
||||
#include <my_pthread.h>
|
||||
static pthread_mutex_t THR_LOCK_dbug;
|
||||
|
||||
/* this mutex protects all sf_* variables, and nothing else*/
|
||||
static pthread_mutex_t sf_mutex;
|
||||
|
||||
static CODE_STATE *code_state(void)
|
||||
{
|
||||
CODE_STATE *cs, **cs_ptr;
|
||||
@ -329,6 +339,7 @@ static CODE_STATE *code_state(void)
|
||||
{
|
||||
init_done=TRUE;
|
||||
pthread_mutex_init(&THR_LOCK_dbug, NULL);
|
||||
pthread_mutex_init(&sf_mutex, NULL);
|
||||
bzero(&init_settings, sizeof(init_settings));
|
||||
init_settings.out_file=stderr;
|
||||
init_settings.flags=OPEN_APPEND;
|
||||
@ -341,8 +352,8 @@ static CODE_STATE *code_state(void)
|
||||
cs=(CODE_STATE*) DbugMalloc(sizeof(*cs));
|
||||
bzero((uchar*) cs,sizeof(*cs));
|
||||
cs->process= db_process ? db_process : "dbug";
|
||||
cs->func="?func";
|
||||
cs->file="?file";
|
||||
cs->func= unknown_func;
|
||||
cs->file= unknown_file;
|
||||
cs->stack=&init_settings;
|
||||
*cs_ptr= cs;
|
||||
}
|
||||
@ -625,6 +636,12 @@ int DbugParse(CODE_STATE *cs, const char *control)
|
||||
else
|
||||
stack->flags |= TIMESTAMP_ON;
|
||||
break;
|
||||
case 'S':
|
||||
if (sign < 0)
|
||||
stack->flags &= ~SANITY_CHECK_ON;
|
||||
else
|
||||
stack->flags |= SANITY_CHECK_ON;
|
||||
break;
|
||||
}
|
||||
if (!*end)
|
||||
break;
|
||||
@ -988,6 +1005,7 @@ int _db_explain_ (CODE_STATE *cs, char *buf, size_t len)
|
||||
op_bool_to_buf('r', cs->stack->sub_level != 0);
|
||||
op_intf_to_buf('t', cs->stack->maxdepth, MAXDEPTH, TRACING);
|
||||
op_bool_to_buf('T', cs->stack->flags & TIMESTAMP_ON);
|
||||
op_bool_to_buf('S', cs->stack->flags & SANITY_CHECK_ON);
|
||||
|
||||
*buf= '\0';
|
||||
return 0;
|
||||
@ -1089,6 +1107,8 @@ void _db_enter_(const char *_func_, const char *_file_,
|
||||
if (!TRACING) break;
|
||||
/* fall through */
|
||||
case DO_TRACE:
|
||||
if ((cs->stack->flags & SANITY_CHECK_ON) && sf_sanity())
|
||||
cs->stack->flags &= ~SANITY_CHECK_ON;
|
||||
if (TRACING)
|
||||
{
|
||||
if (!cs->locked)
|
||||
@ -1144,6 +1164,8 @@ void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_)
|
||||
|
||||
if (DoTrace(cs) & DO_TRACE)
|
||||
{
|
||||
if ((cs->stack->flags & SANITY_CHECK_ON) && sf_sanity())
|
||||
cs->stack->flags &= ~SANITY_CHECK_ON;
|
||||
if (TRACING)
|
||||
{
|
||||
if (!cs->locked)
|
||||
@ -1592,8 +1614,9 @@ void _db_end_()
|
||||
called after dbug was initialized
|
||||
*/
|
||||
_dbug_on_= 1;
|
||||
get_code_state_or_return;
|
||||
cs= code_state();
|
||||
|
||||
if (cs)
|
||||
while ((discard= cs->stack))
|
||||
{
|
||||
if (discard == &init_settings)
|
||||
@ -1603,8 +1626,6 @@ void _db_end_()
|
||||
}
|
||||
tmp= init_settings;
|
||||
|
||||
/* Use mutex lock to make it less likely anyone access out_file */
|
||||
pthread_mutex_lock(&THR_LOCK_dbug);
|
||||
init_settings.flags= OPEN_APPEND;
|
||||
init_settings.out_file= stderr;
|
||||
init_settings.maxdepth= 0;
|
||||
@ -1613,8 +1634,8 @@ void _db_end_()
|
||||
init_settings.functions= 0;
|
||||
init_settings.keywords= 0;
|
||||
init_settings.processes= 0;
|
||||
pthread_mutex_unlock(&THR_LOCK_dbug);
|
||||
FreeState(cs, &tmp, 0);
|
||||
sf_terminate();
|
||||
}
|
||||
|
||||
|
||||
@ -1904,7 +1925,7 @@ static void DBUGOpenFile(CODE_STATE *cs,
|
||||
|
||||
static void DBUGCloseFile(CODE_STATE *cs, FILE *fp)
|
||||
{
|
||||
if (fp && fp != stderr && fp != stdout && fclose(fp) == EOF)
|
||||
if (cs && fp && fp != stderr && fp != stdout && fclose(fp) == EOF)
|
||||
{
|
||||
if (!cs->locked)
|
||||
pthread_mutex_lock(&THR_LOCK_dbug);
|
||||
@ -2140,19 +2161,333 @@ const char* _db_get_func_(void)
|
||||
return cs->func;
|
||||
}
|
||||
|
||||
/*
|
||||
prints the error message, followed by a stack trace
|
||||
of the specified depth
|
||||
*/
|
||||
static void DbugErr(CODE_STATE *cs, uint depth, const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
|
||||
#else
|
||||
if (cs || ((cs= code_state())))
|
||||
{
|
||||
uint i= depth;
|
||||
struct _db_stack_frame_ *frame= cs->framep;
|
||||
while (i-- && frame)
|
||||
{
|
||||
fprintf(stderr, ", at %s", frame->func);
|
||||
frame= frame->prev;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
memory debugger
|
||||
based on safemalloc, memory sub-system, written by Bjorn Benson
|
||||
********************************************************************/
|
||||
|
||||
#ifndef SF_REMEMBER_FRAMES
|
||||
#define SF_REMEMBER_FRAMES 16
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dummy function, workaround for MySQL bug#14420 related
|
||||
* build failure on a platform where linking with an empty
|
||||
* archive fails.
|
||||
*
|
||||
* This block can be removed as soon as a fix for bug#14420
|
||||
* is implemented.
|
||||
Structure that stores information of an allocated memory block
|
||||
The data is at &struct_adr+sizeof(struct irem)
|
||||
Note that sizeof(struct st_irem) % sizeof(double) == 0
|
||||
*/
|
||||
int i_am_a_dummy_function() {
|
||||
struct st_irem
|
||||
{
|
||||
struct st_irem *next; /* Linked list of structures */
|
||||
struct st_irem *prev; /* Other link */
|
||||
size_t datasize; /* Size requested */
|
||||
const char *frame[SF_REMEMBER_FRAMES]; /* call stack */
|
||||
uint32 marker; /* Underrun marker value */
|
||||
};
|
||||
|
||||
/*
|
||||
DBUG_MALLOC/DBUG_REALLOC/DBUG_FREE can be called even
|
||||
before dbug is initialized. We cannot properly take into account
|
||||
these calls, but we can at least wrap allocated memory
|
||||
in st_irem's and check for overrun/underruns.
|
||||
These special irem's - that are not linked into a global list -
|
||||
are distinguished by a special value in the 'next' pointer.
|
||||
*/
|
||||
#define NOT_LINKED ((struct st_irem *)1)
|
||||
|
||||
size_t sf_malloc_mem_limit= (intptr)~0ULL;
|
||||
static size_t sf_malloc_cur_memory= 0L; /* Current memory usage */
|
||||
static size_t sf_malloc_max_memory= 0L; /* Maximum memory usage */
|
||||
|
||||
static int sf_malloc_count= 0; /* Number of allocated chunks */
|
||||
|
||||
static void *sf_min_adress= (void*) (intptr)~0ULL,
|
||||
*sf_max_adress= 0;
|
||||
|
||||
static struct st_irem *sf_malloc_root = 0;
|
||||
|
||||
#define MAGICSTART 0x14235296 /* A magic value for underrun key */
|
||||
|
||||
#define MAGICEND0 0x68 /* Magic values for overrun keys */
|
||||
#define MAGICEND1 0x34 /* " */
|
||||
#define MAGICEND2 0x7A /* " */
|
||||
#define MAGICEND3 0x15 /* " */
|
||||
|
||||
static int bad_ptr(const char *where, void *ptr);
|
||||
static void free_memory(void *ptr);
|
||||
|
||||
/*
|
||||
* FUNCTION
|
||||
*
|
||||
* _db_malloc_ allocates memory
|
||||
*
|
||||
* SYNOPSIS
|
||||
*
|
||||
* void *_db_malloc_(size_t size)
|
||||
* size_t size; Bytes to allocate
|
||||
*/
|
||||
|
||||
void *_db_malloc_(size_t size)
|
||||
{
|
||||
CODE_STATE *cs= code_state();
|
||||
struct st_irem *irem;
|
||||
uchar *data;
|
||||
struct _db_stack_frame_ *frame;
|
||||
int i= 0;
|
||||
|
||||
if (size + sf_malloc_cur_memory > sf_malloc_mem_limit)
|
||||
irem= 0;
|
||||
else
|
||||
irem= (struct st_irem *) malloc (sizeof(struct st_irem) + size + 4);
|
||||
|
||||
if (!irem)
|
||||
return 0;
|
||||
|
||||
compile_time_assert(sizeof(struct st_irem) % sizeof(double) == 0);
|
||||
|
||||
/* Fill up the structure */
|
||||
data= (uchar*) (irem + 1);
|
||||
irem->datasize= size;
|
||||
irem->prev= 0;
|
||||
irem->marker= MAGICSTART;
|
||||
data[size + 0]= MAGICEND0;
|
||||
data[size + 1]= MAGICEND1;
|
||||
data[size + 2]= MAGICEND2;
|
||||
data[size + 3]= MAGICEND3;
|
||||
|
||||
if (cs && cs->framep)
|
||||
{
|
||||
for (frame= cs->framep;
|
||||
i < SF_REMEMBER_FRAMES && frame->func != unknown_func;
|
||||
i++, frame= frame->prev)
|
||||
irem->frame[i]= frame->func;
|
||||
}
|
||||
|
||||
if (i < SF_REMEMBER_FRAMES)
|
||||
irem->frame[i]= unknown_func;
|
||||
if (i==0)
|
||||
irem->frame[0]= (char*)1;
|
||||
|
||||
if (init_done)
|
||||
{
|
||||
pthread_mutex_lock(&sf_mutex);
|
||||
/* Add this structure to the linked list */
|
||||
if ((irem->next= sf_malloc_root))
|
||||
sf_malloc_root->prev= irem;
|
||||
sf_malloc_root= irem;
|
||||
|
||||
/* Keep the statistics */
|
||||
sf_malloc_count++;
|
||||
sf_malloc_cur_memory+= size;
|
||||
set_if_bigger(sf_malloc_max_memory, sf_malloc_cur_memory);
|
||||
set_if_smaller(sf_min_adress, (void*)data);
|
||||
set_if_bigger(sf_max_adress, (void*)data);
|
||||
pthread_mutex_unlock(&sf_mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_if_bigger(sf_malloc_max_memory, sf_malloc_cur_memory);
|
||||
set_if_smaller(sf_min_adress, (void*)data);
|
||||
set_if_bigger(sf_max_adress, (void*)data);
|
||||
irem->next= NOT_LINKED;
|
||||
}
|
||||
|
||||
TRASH_ALLOC(data, size);
|
||||
return data;
|
||||
}
|
||||
|
||||
void *_db_realloc_(void *ptr, size_t size)
|
||||
{
|
||||
char *data;
|
||||
|
||||
if (!ptr)
|
||||
return _db_malloc_(size);
|
||||
|
||||
if (bad_ptr("Reallocating", ptr))
|
||||
return 0;
|
||||
|
||||
if ((data= _db_malloc_(size)))
|
||||
{
|
||||
struct st_irem *irem= (struct st_irem *)ptr - 1;
|
||||
set_if_smaller(size, irem->datasize);
|
||||
memcpy(data, ptr, size);
|
||||
free_memory(ptr);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void _db_free_(void *ptr)
|
||||
{
|
||||
if (!ptr || bad_ptr("Freeing", ptr))
|
||||
return;
|
||||
|
||||
free_memory(ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
static void free_memory(void *ptr)
|
||||
{
|
||||
struct st_irem *irem= (struct st_irem *)ptr - 1;
|
||||
|
||||
if (irem->next != NOT_LINKED)
|
||||
{
|
||||
pthread_mutex_lock(&sf_mutex);
|
||||
/* Remove this structure from the linked list */
|
||||
if (irem->prev)
|
||||
irem->prev->next= irem->next;
|
||||
else
|
||||
sf_malloc_root= irem->next;
|
||||
|
||||
if (irem->next)
|
||||
irem->next->prev= irem->prev;
|
||||
|
||||
/* Handle the statistics */
|
||||
sf_malloc_cur_memory-= irem->datasize;
|
||||
sf_malloc_count--;
|
||||
pthread_mutex_unlock(&sf_mutex);
|
||||
}
|
||||
|
||||
/* only trash the data and magic values, but keep the stack trace */
|
||||
TRASH_FREE((uchar*)(irem + 1) - 4, irem->datasize + 8);
|
||||
free(irem);
|
||||
return;
|
||||
}
|
||||
|
||||
#define SF_ADD_NL 1
|
||||
#define SF_USE_SAFE_PRINT 2
|
||||
static void print_allocated_at(struct st_irem *irem, int flags)
|
||||
{
|
||||
int i;
|
||||
const char *allocated= flags & SF_ADD_NL ? "Allocated" : ", allocated";
|
||||
|
||||
for (i=0;
|
||||
i < SF_REMEMBER_FRAMES && irem->frame[i] != unknown_func;
|
||||
i++)
|
||||
{
|
||||
fprintf(stderr, "%s at ", i ? "," : allocated);
|
||||
if (flags & SF_USE_SAFE_PRINT)
|
||||
my_safe_print_str(irem->frame[i], 80);
|
||||
else
|
||||
fputs(irem->frame[i], stderr);
|
||||
}
|
||||
if (i && (flags & SF_ADD_NL))
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static int bad_ptr(const char *where, void *ptr)
|
||||
{
|
||||
struct st_irem *irem= (struct st_irem *)ptr - 1;
|
||||
const uchar *magicend;
|
||||
|
||||
if (((intptr) ptr) % sizeof(double))
|
||||
{
|
||||
DbugErr(0, SF_REMEMBER_FRAMES, "Error: %s wrong aligned pointer", where);
|
||||
return 1;
|
||||
}
|
||||
if (ptr < sf_min_adress || ptr > sf_max_adress)
|
||||
{
|
||||
DbugErr(0, SF_REMEMBER_FRAMES, "Error: %s pointer out of range", where);
|
||||
return 1;
|
||||
}
|
||||
if (irem->marker != MAGICSTART)
|
||||
{
|
||||
DbugErr(0, SF_REMEMBER_FRAMES,
|
||||
"Error: %s unallocated data or underrun buffer", where);
|
||||
/*
|
||||
we cannot use print_allocated_at here:
|
||||
if the memory was not allocated, there's nothing to print,
|
||||
if it was allocated and underrun, call stack may be corrupted
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
magicend= (uchar*)ptr + irem->datasize;
|
||||
if (magicend[0] != MAGICEND0 ||
|
||||
magicend[1] != MAGICEND1 ||
|
||||
magicend[2] != MAGICEND2 ||
|
||||
magicend[3] != MAGICEND3)
|
||||
{
|
||||
DbugErr(0, SF_REMEMBER_FRAMES, "Error: %s overrun buffer", where);
|
||||
print_allocated_at(irem, SF_ADD_NL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* check all allocated memory list for consistency */
|
||||
static int sf_sanity()
|
||||
{
|
||||
struct st_irem *irem;
|
||||
int flag= 0;
|
||||
int count= 0;
|
||||
|
||||
pthread_mutex_lock(&sf_mutex);
|
||||
count= sf_malloc_count;
|
||||
for (irem= sf_malloc_root; irem && count > 0; count--, irem= irem->next)
|
||||
flag+= bad_ptr("Safemalloc", irem + 1);
|
||||
pthread_mutex_unlock(&sf_mutex);
|
||||
if (count || irem)
|
||||
{
|
||||
DbugErr(0, SF_REMEMBER_FRAMES, "Error: Safemalloc link list destroyed");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION
|
||||
*
|
||||
* sf_terminate Report on all the memory pieces that have not been free'd
|
||||
*
|
||||
* SYNOPSIS
|
||||
*
|
||||
* void sf_terminate()
|
||||
*/
|
||||
|
||||
static void sf_terminate()
|
||||
{
|
||||
struct st_irem *irem;
|
||||
|
||||
sf_sanity();
|
||||
|
||||
/* Report on all the memory that was allocated but not free'd */
|
||||
if ((irem= sf_malloc_root))
|
||||
{
|
||||
while (irem)
|
||||
{
|
||||
fprintf(stderr, "Warning: %6lu bytes at %p are not freed", (ulong) irem->datasize, irem + 1);
|
||||
print_allocated_at(irem, SF_USE_SAFE_PRINT);
|
||||
fprintf(stderr, "\n");
|
||||
irem= irem->next;
|
||||
}
|
||||
fprintf(stderr, "Memory lost: %lu bytes in %d chunks\n",
|
||||
(ulong) sf_malloc_cur_memory, sf_malloc_count);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -988,6 +988,14 @@ Most useful with
|
||||
.B DBUG_PUSH
|
||||
macros used to temporarily alter the
|
||||
debugger state.
|
||||
.LI S
|
||||
When compiled with
|
||||
.I safemalloc
|
||||
this flag invokes "sanity" memory checks (for overwrites/underwrites)
|
||||
on each
|
||||
.B DBUG_ENTER
|
||||
and
|
||||
.B DBUG_RETURN.
|
||||
.LI t[,N]
|
||||
Enable function control flow tracing.
|
||||
The maximum nesting depth is specified by N, and defaults to
|
||||
|
@ -66,6 +66,9 @@ extern void _db_unlock_file_(void);
|
||||
extern FILE *_db_fp_(void);
|
||||
extern void _db_flush_();
|
||||
extern const char* _db_get_func_(void);
|
||||
extern void *_db_malloc_(size_t size);
|
||||
extern void *_db_realloc_(void *ptr, size_t size);
|
||||
extern void _db_free_(void *ptr);
|
||||
|
||||
#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_; \
|
||||
_db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_)
|
||||
@ -98,6 +101,10 @@ extern const char* _db_get_func_(void);
|
||||
#define DBUG_EXPLAIN_INITIAL(buf,len) _db_explain_init_((buf),(len))
|
||||
#define DEBUGGER_OFF do { _dbug_on_= 0; } while(0)
|
||||
#define DEBUGGER_ON do { _dbug_on_= 1; } while(0)
|
||||
#define DBUG_MALLOC(SIZE) _db_malloc_(SIZE)
|
||||
#define DBUG_REALLOC(PTR,SIZE) _db_realloc_(PTR,SIZE)
|
||||
#define DBUG_FREE(PTR) _db_free_(PTR)
|
||||
|
||||
#ifndef __WIN__
|
||||
#define DBUG_ABORT() (_db_flush_(), abort())
|
||||
#else
|
||||
@ -163,6 +170,9 @@ extern void _db_suicide_();
|
||||
#define DBUG_EXPLAIN_INITIAL(buf,len)
|
||||
#define DEBUGGER_OFF do { } while(0)
|
||||
#define DEBUGGER_ON do { } while(0)
|
||||
#define DBUG_MALLOC(SIZE) malloc(SIZE)
|
||||
#define DBUG_REALLOC(PTR,SIZE) realloc(PTR,SIZE)
|
||||
#define DBUG_FREE(PTR) free(PTR)
|
||||
#define DBUG_ABORT() do { } while(0)
|
||||
#define DBUG_CRASH_ENTER(func)
|
||||
#define DBUG_CRASH_RETURN(val) do { return(val); } while(0)
|
||||
|
@ -28,24 +28,7 @@ typedef struct my_aio_result {
|
||||
} my_aio_result;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_valgrind
|
||||
#define IF_VALGRIND(A,B) A
|
||||
#else
|
||||
#define IF_VALGRIND(A,B) B
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_valgrind) && defined(HAVE_VALGRIND_MEMCHECK_H)
|
||||
# include <valgrind/memcheck.h>
|
||||
# define MEM_UNDEFINED(a,len) VALGRIND_MAKE_MEM_UNDEFINED(a,len)
|
||||
# define MEM_NOACCESS(a,len) VALGRIND_MAKE_MEM_NOACCESS(a,len)
|
||||
# define MEM_CHECK_ADDRESSABLE(a,len) VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a,len)
|
||||
# define MEM_CHECK_DEFINED(a,len) VALGRIND_CHECK_MEM_IS_DEFINED(a,len)
|
||||
#else /* HAVE_VALGRIND */
|
||||
# define MEM_UNDEFINED(a,len) ((void) 0)
|
||||
# define MEM_NOACCESS(a,len) ((void) 0)
|
||||
# define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0)
|
||||
# define MEM_CHECK_DEFINED(a,len) ((void) 0)
|
||||
#endif /* HAVE_VALGRIND */
|
||||
#include <my_valgrind.h>
|
||||
|
||||
#include <my_pthread.h>
|
||||
|
||||
@ -168,12 +151,6 @@ extern void *my_memdup(const void *from,size_t length,myf MyFlags);
|
||||
extern char *my_strdup(const char *from,myf MyFlags);
|
||||
extern char *my_strndup(const char *from, size_t length,
|
||||
myf MyFlags);
|
||||
#ifdef SAFEMALLOC
|
||||
#define TRASH(A,B) do { bfill(A, B, 0x8F); MEM_UNDEFINED(A, B); } while (0)
|
||||
#else
|
||||
#define TRASH(A,B) do{MEM_CHECK_ADDRESSABLE(A,B);MEM_UNDEFINED(A,B);} while (0)
|
||||
#endif
|
||||
|
||||
#if defined(ENABLED_DEBUG_SYNC)
|
||||
extern void (*debug_sync_C_callback_ptr)(const char *, size_t);
|
||||
#define DEBUG_SYNC_C(_sync_point_name_) do { \
|
||||
|
46
include/my_valgrind.h
Normal file
46
include/my_valgrind.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* Copyright (C) 2010 Monty Program Ab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
/* Some defines to make it easier to use valgrind */
|
||||
|
||||
#ifdef HAVE_valgrind
|
||||
#define IF_VALGRIND(A,B) A
|
||||
#else
|
||||
#define IF_VALGRIND(A,B) B
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_valgrind) && defined(HAVE_VALGRIND_MEMCHECK_H)
|
||||
# include <valgrind/memcheck.h>
|
||||
# define MEM_UNDEFINED(a,len) VALGRIND_MAKE_MEM_UNDEFINED(a,len)
|
||||
# define MEM_NOACCESS(a,len) VALGRIND_MAKE_MEM_NOACCESS(a,len)
|
||||
# define MEM_CHECK_ADDRESSABLE(a,len) VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a,len)
|
||||
# define MEM_CHECK_DEFINED(a,len) VALGRIND_CHECK_MEM_IS_DEFINED(a,len)
|
||||
#else /* HAVE_VALGRIND */
|
||||
# define MEM_UNDEFINED(a,len) ((void) 0)
|
||||
# define MEM_NOACCESS(a,len) ((void) 0)
|
||||
# define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0)
|
||||
# define MEM_CHECK_DEFINED(a,len) ((void) 0)
|
||||
#endif /* HAVE_VALGRIND */
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
#define TRASH_FILL(A,B,C) do { bfill(A, B, C); MEM_UNDEFINED(A, B); } while (0)
|
||||
#else
|
||||
#define TRASH_FILL(A,B,C) do{ MEM_CHECK_ADDRESSABLE(A,B);MEM_UNDEFINED(A,B);} while (0)
|
||||
#endif
|
||||
#define TRASH_ALLOC(A,B) TRASH_FILL(A,B,0xA5)
|
||||
#define TRASH_FREE(A,B) TRASH_FILL(A,B,0x8F)
|
||||
#define TRASH(A,B) TRASH_FREE(A,B)
|
||||
|
@ -3421,7 +3421,6 @@ sub mysql_install_db {
|
||||
mtr_add_arg($args, "--loose-skip-ndbcluster");
|
||||
mtr_add_arg($args, "--loose-skip-aria");
|
||||
mtr_add_arg($args, "--disable-sync-frm");
|
||||
mtr_add_arg($args, "--loose-disable-debug");
|
||||
mtr_add_arg($args, "--tmpdir=%s", "$opt_vardir/tmp/");
|
||||
mtr_add_arg($args, "--core-file");
|
||||
|
||||
|
@ -235,6 +235,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
|
||||
mem_root->used= next;
|
||||
mem_root->first_block_usage= 0;
|
||||
}
|
||||
TRASH_ALLOC(point, length);
|
||||
DBUG_PRINT("exit",("ptr: 0x%lx", (ulong) point));
|
||||
DBUG_RETURN((void*) point);
|
||||
#endif
|
||||
|
@ -35,10 +35,10 @@ void *my_malloc(size_t size, myf my_flags)
|
||||
if (!size)
|
||||
size=1;
|
||||
|
||||
point= malloc(size);
|
||||
point= DBUG_MALLOC(size);
|
||||
DBUG_EXECUTE_IF("simulate_out_of_memory",
|
||||
{
|
||||
free(point);
|
||||
my_free(point);
|
||||
point= NULL;
|
||||
});
|
||||
|
||||
@ -81,7 +81,7 @@ void *my_realloc(void *oldpoint, size_t size, myf my_flags)
|
||||
DBUG_ASSERT(size > 0);
|
||||
if (!oldpoint && (my_flags & MY_ALLOW_ZERO_PTR))
|
||||
DBUG_RETURN(my_malloc(size, my_flags));
|
||||
if ((point= realloc(oldpoint, size)) == NULL)
|
||||
if ((point= DBUG_REALLOC(oldpoint, size)) == NULL)
|
||||
{
|
||||
if (my_flags & MY_FREE_ON_ERROR)
|
||||
my_free(oldpoint);
|
||||
@ -107,7 +107,7 @@ void my_free(void *ptr)
|
||||
{
|
||||
DBUG_ENTER("my_free");
|
||||
DBUG_PRINT("my",("ptr: %p", ptr));
|
||||
free(ptr);
|
||||
DBUG_FREE(ptr);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -117,12 +117,8 @@ static int safe_print_str(const char *addr, int max_len)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Output a new line if something was printed. */
|
||||
if (total != (size_t) max_len)
|
||||
fputc('\n', stderr);
|
||||
|
||||
if (nbytes == -1)
|
||||
fprintf(stderr, "Can't read from address %p: %m.\n", addr);
|
||||
fprintf(stderr, "Can't read from address %p: %m.", addr);
|
||||
|
||||
close(fd);
|
||||
|
||||
@ -144,13 +140,12 @@ void my_safe_print_str(const char* val, int max_len)
|
||||
|
||||
if (!PTR_SANE(val))
|
||||
{
|
||||
fprintf(stderr, "is an invalid pointer\n");
|
||||
fprintf(stderr, "is an invalid pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
for (; max_len && PTR_SANE(val) && *val; --max_len)
|
||||
fputc(*val++, stderr);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
#if defined(HAVE_PRINTSTACK)
|
||||
@ -704,11 +699,11 @@ void my_safe_print_str(const char *val, int len)
|
||||
{
|
||||
__try
|
||||
{
|
||||
fprintf(stderr, "%.*s\n", len, val);
|
||||
fprintf(stderr, "%.*s", len, val);
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
fprintf(stderr, "is an invalid string pointer\n");
|
||||
fprintf(stderr, "is an invalid string pointer");
|
||||
}
|
||||
}
|
||||
#endif /*__WIN__*/
|
||||
|
@ -2610,7 +2610,7 @@ the thread stack. Please read http://dev.mysql.com/doc/mysql/en/linux.html\n\n",
|
||||
"Some pointers may be invalid and cause the dump to abort.\n");
|
||||
fprintf(stderr, "Query (%p): ", thd->query());
|
||||
my_safe_print_str(thd->query(), min(1024, thd->query_length()));
|
||||
fprintf(stderr, "Connection ID (thread ID): %lu\n", (ulong) thd->thread_id);
|
||||
fprintf(stderr, "\nConnection ID (thread ID): %lu\n", (ulong) thd->thread_id);
|
||||
fprintf(stderr, "Status: %s\n", kreason);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
@ -7653,9 +7653,7 @@ static void translog_force_current_buffer_to_finish()
|
||||
we can not copy it and will not overwrite later
|
||||
*/
|
||||
new_buffer->skipped_data= current_page_fill;
|
||||
#ifndef DBUG_OFF
|
||||
memset(new_buffer->buffer, 0xa5, current_page_fill);
|
||||
#endif
|
||||
TRASH_ALLOC(new_buffer->buffer, current_page_fill);
|
||||
DBUG_ASSERT(new_buffer->skipped_data < TRANSLOG_PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user