Loading dbug/dbug.c +22 −6 Original line number Diff line number Diff line Loading @@ -21,7 +21,8 @@ * all copies and derivative works. Thank you. * * * * The author makes no warranty of any kind with respect to this * * product and explicitly disclaims any implied warranties of mer- * * product and explicitly disclaims any implied warranties of mer- *ct_lex.table_list.first=0; thd->lex.selec * chantability or fitness for any particular purpose. * * * ****************************************************************************** Loading Loading @@ -58,7 +59,7 @@ * seismo!bpa!sjuvax!bbanerje * * Michael Widenius: * DBUG_DUMP - To dump a pice of memory. * DBUG_DUMP - To dump a block of memory. * PUSH_FLAG "O" - To be used insted of "o" if we don't * want flushing (for slow systems) * PUSH_FLAG "A" - as 'O', but we will append to the out file instead Loading Loading @@ -707,7 +708,13 @@ char ***_sframep_ __attribute__((unused))) int save_errno=errno; if (!init_done) _db_push_ (_DBUG_START_CONDITION_); state=code_state(); /* Sasha: the test below is so we could call functions with DBUG_ENTER before my_thread_init(). I needed this because I suspected corruption of a block allocated by my_thread_init() itself, so I wanted to use my_malloc()/my_free() in my_thread_init()/my_thread_end() */ if (!(state=code_state())) return; *_sfunc_ = state->func; *_sfile_ = state->file; Loading Loading @@ -855,6 +862,9 @@ uint _line_, const char *keyword) { CODE_STATE *state=code_state(); /* Sasha: pre-my_thread_init() safety */ if (!state) return; state->u_line = _line_; state->u_keyword = (char*) keyword; } Loading Loading @@ -890,7 +900,9 @@ void _db_doprnt_ (const char *format,...) { va_list args; CODE_STATE *state; state=code_state(); /* Sasha: pre-my_thread_init() safety */ if (!(state=code_state())) return; va_start(args,format); Loading Loading @@ -942,7 +954,9 @@ uint length) int pos; char dbuff[90]; CODE_STATE *state; state=code_state(); /* Sasha: pre-my_thread_init() safety */ if (!(state=code_state())) return; if (_db_keyword_ ((char*) keyword)) { Loading Loading @@ -1224,7 +1238,9 @@ const char *keyword) if (!init_done) _db_push_ (""); state=code_state(); /* Sasha: pre-my_thread_init() safety */ if (!(state=code_state())) return FALSE; result = FALSE; if (DEBUGGING && state->level <= stack -> maxdepth && Loading include/my_sys.h +4 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,10 @@ extern int NEAR my_errno; /* Last error in mysys */ #define NORMAL_SAFEMALLOC sf_malloc_quick=0 extern uint sf_malloc_prehunc,sf_malloc_endhunc,sf_malloc_quick; extern ulonglong safemalloc_mem_limit; /* keep track of shutdown,signal, and main threads so that my_end() will not report errors with them */ extern pthread_t shutdown_th, main_th,signal_th; #define CALLER_INFO_PROTO , const char *sFile, uint uLine #define CALLER_INFO , __FILE__, __LINE__ #define ORIG_CALLER_INFO , sFile, uLine Loading mysys/my_static.h +6 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ struct irem { my_string _sFileName; /* File in which memory was new'ed */ uint _uLineNum; /* Line number in above file */ uint _uDataSize; /* Size requested */ pthread_t thread_id; long _lSpecialValue; /* Underrun marker value */ }; Loading @@ -56,6 +57,11 @@ extern const char *soundex_map; extern USED_MEM* my_once_root_block; extern uint my_once_extra; /* these threads are exept from safemalloc leak scrutiny unless PEDANTIC_SAFEMALLOC is defined */ extern pthread_t signal_thread,kill_thread; #ifndef HAVE_TEMPNAM extern int _my_tempnam_used; #endif Loading mysys/my_thr_init.c +34 −5 Original line number Diff line number Diff line Loading @@ -105,19 +105,33 @@ static long thread_id=0; my_bool my_thread_init(void) { struct st_my_thread_var *tmp; #ifdef EXTRA_DEBUG fprintf(stderr,"my_thread_init(): thread_id=%ld\n",pthread_self()); #endif #if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX) pthread_mutex_lock(&THR_LOCK_lock); #endif #if !defined(__WIN__) || defined(USE_TLS) if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys)) { #ifdef EXTRA_DEBUG fprintf(stderr,"my_thread_init() called more than once in thread %ld\n", pthread_self()); #endif pthread_mutex_unlock(&THR_LOCK_lock); return 0; /* Safequard */ } /* We must have many calloc() here because these are freed on pthread_exit */ /* Sasha: the above comment does not make sense. I have changed calloc() to equivalent my_malloc() but it was calloc() before. It seems like the comment is out of date - we always call my_thread_end() before pthread_exit() to clean up. Note that I have also fixed up DBUG code to be able to call it from my_thread_init() */ if (!(tmp=(struct st_my_thread_var *) calloc(1,sizeof(struct st_my_thread_var)))) my_malloc(sizeof(struct st_my_thread_var),MYF(MY_WME|MY_ZEROFILL)))) { pthread_mutex_unlock(&THR_LOCK_lock); return 1; Loading @@ -125,6 +139,9 @@ my_bool my_thread_init(void) pthread_setspecific(THR_KEY_mysys,tmp); #else /* Sasha: TODO - explain what exactly we are doing on Windows At first glance, I have a hard time following the code */ if (THR_KEY_mysys.id) /* Already initialized */ { #if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX) Loading @@ -146,9 +163,18 @@ my_bool my_thread_init(void) void my_thread_end(void) { struct st_my_thread_var *tmp=my_thread_var; #ifdef EXTRA_DEBUG fprintf(stderr,"my_thread_end(): tmp=%p,thread_id=%ld\n", tmp,pthread_self()); #endif if (tmp) { #if !defined(DBUG_OFF) /* Sasha: tmp->dbug is allocated inside DBUG library so for now we will not mess with trying to use my_malloc()/ my_free(), but in the future it would be nice to figure out a way to do it */ if (tmp->dbug) { free(tmp->dbug); Loading @@ -160,13 +186,16 @@ void my_thread_end(void) #endif pthread_mutex_destroy(&tmp->mutex); #if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS) free(tmp); #endif } #if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS) /* we need to setspecific to 0 BEFORE we call my_free, as my_free uses some DBUG_ macros that will use the follow the specific pointer after the block it is pointing to has been freed if specific does not get reset first */ pthread_setspecific(THR_KEY_mysys,0); my_free((gptr)tmp,MYF(MY_WME)); #endif } } struct st_my_thread_var *_my_thread_var(void) { Loading mysys/safemalloc.c +69 −1 Original line number Diff line number Diff line Loading @@ -73,14 +73,25 @@ #include "mysys_err.h" ulonglong safemalloc_mem_limit = ~(ulonglong)0; pthread_t shutdown_th=0,main_th=0,signal_th=0; #define pNext tInt._pNext #define pPrev tInt._pPrev #define sFileName tInt._sFileName #define uLineNum tInt._uLineNum #define uDataSize tInt._uDataSize #define thread_id tInt.thread_id #define lSpecialValue tInt._lSpecialValue #ifndef PEDANTIC_SAFEMALLOC static int sf_malloc_tampered = 0; /* set to 1 after TERMINATE() if we had to fiddle with cNewCount and the linked list of blocks so that _sanity() will not fuss when it is not supposed to */ #endif /* Static functions prototypes */ static int check_ptr(const char *where, byte *ptr, const char *sFile, Loading Loading @@ -174,6 +185,7 @@ gptr _mymalloc (uint uSize, const char *sFile, uint uLine, myf MyFlags) pTmp -> sFileName = (my_string) sFile; pTmp -> uLineNum = uLine; pTmp -> uDataSize = uSize; pTmp->thread_id = pthread_self(); pTmp -> pPrev = NULL; /* Add this remember structure to the linked list */ Loading Loading @@ -359,6 +371,12 @@ static int check_ptr(const char *where, byte *ptr, const char *sFile, return 0; } static int legal_leak(struct remember* pPtr) { return pthread_self() == pPtr->thread_id || main_th == pPtr->thread_id || shutdown_th == pPtr->thread_id || signal_th == pPtr->thread_id; } /* * TERMINATE(FILE *file) Loading @@ -376,6 +394,47 @@ void TERMINATE (FILE *file) /* NEW and the number of calls to FREE. >0 means more */ /* NEWs than FREEs. <0, etc. */ #ifndef PEDANTIC_SAFEMALLOC /* Avoid false alarms for blocks that we cannot free before my_end() This does miss some positives, but that is ok. This will only miss failures to free things allocated in the main thread which performs only one-time allocations. If you really need to debug memory allocations in the main thread, #define PEDANTIC_SAFEMALLOC */ if ((pPtr=pRememberRoot)) { while (pPtr) { if (legal_leak(pPtr)) { sf_malloc_tampered=1; cNewCount--; lCurMemory -= pPtr->uDataSize; if (pPtr->pPrev) { struct remember* tmp; tmp = pPtr->pPrev->pNext = pPtr->pNext; if (tmp) tmp->pPrev = pPtr->pPrev; pPtr->pNext = pPtr->pPrev = 0; pPtr = tmp; } else { pRememberRoot = pPtr->pNext; pPtr->pNext = pPtr->pPrev = 0; pPtr = pRememberRoot; if (pPtr) pPtr->pPrev=0; } } else pPtr = pPtr->pNext; } } #endif if (cNewCount) { if (file) Loading @@ -402,10 +461,14 @@ void TERMINATE (FILE *file) if (file) { fprintf (file, "\t%6u bytes at 0x%09lx, allocated at line %4u in '%s'\n", "\t%6u bytes at 0x%09lx, allocated at line %4u in '%s'", pPtr -> uDataSize, (ulong) &(pPtr -> aData[sf_malloc_prehunc]), pPtr -> uLineNum, pPtr -> sFileName); #ifdef THREAD fprintf(file, " in thread %ld", pPtr->thread_id); #endif fprintf(file, "\n"); (void) fflush(file); } DBUG_PRINT("safe", Loading Loading @@ -484,6 +547,10 @@ int _sanity (const char *sFile, uint uLine) uint count=0; pthread_mutex_lock(&THR_LOCK_malloc); #ifndef PEDANTIC_SAFEMALLOC if (sf_malloc_tampered && cNewCount < 0) cNewCount=0; #endif count=cNewCount; for (pTmp = pRememberRoot; pTmp != NULL && count-- ; pTmp = pTmp -> pNext) flag+=_checkchunk (pTmp, sFile, uLine); Loading @@ -492,6 +559,7 @@ int _sanity (const char *sFile, uint uLine) { const char *format="Safemalloc link list destroyed, discovered at '%s:%d'"; fprintf (stderr, format, sFile, uLine); fputc('\n',stderr); fprintf (stderr, "root=%p,count=%d,pTmp=%p\n", pRememberRoot,count,pTmp); (void) fflush(stderr); DBUG_PRINT("safe",(format, sFile, uLine)); flag=1; Loading Loading
dbug/dbug.c +22 −6 Original line number Diff line number Diff line Loading @@ -21,7 +21,8 @@ * all copies and derivative works. Thank you. * * * * The author makes no warranty of any kind with respect to this * * product and explicitly disclaims any implied warranties of mer- * * product and explicitly disclaims any implied warranties of mer- *ct_lex.table_list.first=0; thd->lex.selec * chantability or fitness for any particular purpose. * * * ****************************************************************************** Loading Loading @@ -58,7 +59,7 @@ * seismo!bpa!sjuvax!bbanerje * * Michael Widenius: * DBUG_DUMP - To dump a pice of memory. * DBUG_DUMP - To dump a block of memory. * PUSH_FLAG "O" - To be used insted of "o" if we don't * want flushing (for slow systems) * PUSH_FLAG "A" - as 'O', but we will append to the out file instead Loading Loading @@ -707,7 +708,13 @@ char ***_sframep_ __attribute__((unused))) int save_errno=errno; if (!init_done) _db_push_ (_DBUG_START_CONDITION_); state=code_state(); /* Sasha: the test below is so we could call functions with DBUG_ENTER before my_thread_init(). I needed this because I suspected corruption of a block allocated by my_thread_init() itself, so I wanted to use my_malloc()/my_free() in my_thread_init()/my_thread_end() */ if (!(state=code_state())) return; *_sfunc_ = state->func; *_sfile_ = state->file; Loading Loading @@ -855,6 +862,9 @@ uint _line_, const char *keyword) { CODE_STATE *state=code_state(); /* Sasha: pre-my_thread_init() safety */ if (!state) return; state->u_line = _line_; state->u_keyword = (char*) keyword; } Loading Loading @@ -890,7 +900,9 @@ void _db_doprnt_ (const char *format,...) { va_list args; CODE_STATE *state; state=code_state(); /* Sasha: pre-my_thread_init() safety */ if (!(state=code_state())) return; va_start(args,format); Loading Loading @@ -942,7 +954,9 @@ uint length) int pos; char dbuff[90]; CODE_STATE *state; state=code_state(); /* Sasha: pre-my_thread_init() safety */ if (!(state=code_state())) return; if (_db_keyword_ ((char*) keyword)) { Loading Loading @@ -1224,7 +1238,9 @@ const char *keyword) if (!init_done) _db_push_ (""); state=code_state(); /* Sasha: pre-my_thread_init() safety */ if (!(state=code_state())) return FALSE; result = FALSE; if (DEBUGGING && state->level <= stack -> maxdepth && Loading
include/my_sys.h +4 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,10 @@ extern int NEAR my_errno; /* Last error in mysys */ #define NORMAL_SAFEMALLOC sf_malloc_quick=0 extern uint sf_malloc_prehunc,sf_malloc_endhunc,sf_malloc_quick; extern ulonglong safemalloc_mem_limit; /* keep track of shutdown,signal, and main threads so that my_end() will not report errors with them */ extern pthread_t shutdown_th, main_th,signal_th; #define CALLER_INFO_PROTO , const char *sFile, uint uLine #define CALLER_INFO , __FILE__, __LINE__ #define ORIG_CALLER_INFO , sFile, uLine Loading
mysys/my_static.h +6 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ struct irem { my_string _sFileName; /* File in which memory was new'ed */ uint _uLineNum; /* Line number in above file */ uint _uDataSize; /* Size requested */ pthread_t thread_id; long _lSpecialValue; /* Underrun marker value */ }; Loading @@ -56,6 +57,11 @@ extern const char *soundex_map; extern USED_MEM* my_once_root_block; extern uint my_once_extra; /* these threads are exept from safemalloc leak scrutiny unless PEDANTIC_SAFEMALLOC is defined */ extern pthread_t signal_thread,kill_thread; #ifndef HAVE_TEMPNAM extern int _my_tempnam_used; #endif Loading
mysys/my_thr_init.c +34 −5 Original line number Diff line number Diff line Loading @@ -105,19 +105,33 @@ static long thread_id=0; my_bool my_thread_init(void) { struct st_my_thread_var *tmp; #ifdef EXTRA_DEBUG fprintf(stderr,"my_thread_init(): thread_id=%ld\n",pthread_self()); #endif #if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX) pthread_mutex_lock(&THR_LOCK_lock); #endif #if !defined(__WIN__) || defined(USE_TLS) if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys)) { #ifdef EXTRA_DEBUG fprintf(stderr,"my_thread_init() called more than once in thread %ld\n", pthread_self()); #endif pthread_mutex_unlock(&THR_LOCK_lock); return 0; /* Safequard */ } /* We must have many calloc() here because these are freed on pthread_exit */ /* Sasha: the above comment does not make sense. I have changed calloc() to equivalent my_malloc() but it was calloc() before. It seems like the comment is out of date - we always call my_thread_end() before pthread_exit() to clean up. Note that I have also fixed up DBUG code to be able to call it from my_thread_init() */ if (!(tmp=(struct st_my_thread_var *) calloc(1,sizeof(struct st_my_thread_var)))) my_malloc(sizeof(struct st_my_thread_var),MYF(MY_WME|MY_ZEROFILL)))) { pthread_mutex_unlock(&THR_LOCK_lock); return 1; Loading @@ -125,6 +139,9 @@ my_bool my_thread_init(void) pthread_setspecific(THR_KEY_mysys,tmp); #else /* Sasha: TODO - explain what exactly we are doing on Windows At first glance, I have a hard time following the code */ if (THR_KEY_mysys.id) /* Already initialized */ { #if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX) Loading @@ -146,9 +163,18 @@ my_bool my_thread_init(void) void my_thread_end(void) { struct st_my_thread_var *tmp=my_thread_var; #ifdef EXTRA_DEBUG fprintf(stderr,"my_thread_end(): tmp=%p,thread_id=%ld\n", tmp,pthread_self()); #endif if (tmp) { #if !defined(DBUG_OFF) /* Sasha: tmp->dbug is allocated inside DBUG library so for now we will not mess with trying to use my_malloc()/ my_free(), but in the future it would be nice to figure out a way to do it */ if (tmp->dbug) { free(tmp->dbug); Loading @@ -160,13 +186,16 @@ void my_thread_end(void) #endif pthread_mutex_destroy(&tmp->mutex); #if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS) free(tmp); #endif } #if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS) /* we need to setspecific to 0 BEFORE we call my_free, as my_free uses some DBUG_ macros that will use the follow the specific pointer after the block it is pointing to has been freed if specific does not get reset first */ pthread_setspecific(THR_KEY_mysys,0); my_free((gptr)tmp,MYF(MY_WME)); #endif } } struct st_my_thread_var *_my_thread_var(void) { Loading
mysys/safemalloc.c +69 −1 Original line number Diff line number Diff line Loading @@ -73,14 +73,25 @@ #include "mysys_err.h" ulonglong safemalloc_mem_limit = ~(ulonglong)0; pthread_t shutdown_th=0,main_th=0,signal_th=0; #define pNext tInt._pNext #define pPrev tInt._pPrev #define sFileName tInt._sFileName #define uLineNum tInt._uLineNum #define uDataSize tInt._uDataSize #define thread_id tInt.thread_id #define lSpecialValue tInt._lSpecialValue #ifndef PEDANTIC_SAFEMALLOC static int sf_malloc_tampered = 0; /* set to 1 after TERMINATE() if we had to fiddle with cNewCount and the linked list of blocks so that _sanity() will not fuss when it is not supposed to */ #endif /* Static functions prototypes */ static int check_ptr(const char *where, byte *ptr, const char *sFile, Loading Loading @@ -174,6 +185,7 @@ gptr _mymalloc (uint uSize, const char *sFile, uint uLine, myf MyFlags) pTmp -> sFileName = (my_string) sFile; pTmp -> uLineNum = uLine; pTmp -> uDataSize = uSize; pTmp->thread_id = pthread_self(); pTmp -> pPrev = NULL; /* Add this remember structure to the linked list */ Loading Loading @@ -359,6 +371,12 @@ static int check_ptr(const char *where, byte *ptr, const char *sFile, return 0; } static int legal_leak(struct remember* pPtr) { return pthread_self() == pPtr->thread_id || main_th == pPtr->thread_id || shutdown_th == pPtr->thread_id || signal_th == pPtr->thread_id; } /* * TERMINATE(FILE *file) Loading @@ -376,6 +394,47 @@ void TERMINATE (FILE *file) /* NEW and the number of calls to FREE. >0 means more */ /* NEWs than FREEs. <0, etc. */ #ifndef PEDANTIC_SAFEMALLOC /* Avoid false alarms for blocks that we cannot free before my_end() This does miss some positives, but that is ok. This will only miss failures to free things allocated in the main thread which performs only one-time allocations. If you really need to debug memory allocations in the main thread, #define PEDANTIC_SAFEMALLOC */ if ((pPtr=pRememberRoot)) { while (pPtr) { if (legal_leak(pPtr)) { sf_malloc_tampered=1; cNewCount--; lCurMemory -= pPtr->uDataSize; if (pPtr->pPrev) { struct remember* tmp; tmp = pPtr->pPrev->pNext = pPtr->pNext; if (tmp) tmp->pPrev = pPtr->pPrev; pPtr->pNext = pPtr->pPrev = 0; pPtr = tmp; } else { pRememberRoot = pPtr->pNext; pPtr->pNext = pPtr->pPrev = 0; pPtr = pRememberRoot; if (pPtr) pPtr->pPrev=0; } } else pPtr = pPtr->pNext; } } #endif if (cNewCount) { if (file) Loading @@ -402,10 +461,14 @@ void TERMINATE (FILE *file) if (file) { fprintf (file, "\t%6u bytes at 0x%09lx, allocated at line %4u in '%s'\n", "\t%6u bytes at 0x%09lx, allocated at line %4u in '%s'", pPtr -> uDataSize, (ulong) &(pPtr -> aData[sf_malloc_prehunc]), pPtr -> uLineNum, pPtr -> sFileName); #ifdef THREAD fprintf(file, " in thread %ld", pPtr->thread_id); #endif fprintf(file, "\n"); (void) fflush(file); } DBUG_PRINT("safe", Loading Loading @@ -484,6 +547,10 @@ int _sanity (const char *sFile, uint uLine) uint count=0; pthread_mutex_lock(&THR_LOCK_malloc); #ifndef PEDANTIC_SAFEMALLOC if (sf_malloc_tampered && cNewCount < 0) cNewCount=0; #endif count=cNewCount; for (pTmp = pRememberRoot; pTmp != NULL && count-- ; pTmp = pTmp -> pNext) flag+=_checkchunk (pTmp, sFile, uLine); Loading @@ -492,6 +559,7 @@ int _sanity (const char *sFile, uint uLine) { const char *format="Safemalloc link list destroyed, discovered at '%s:%d'"; fprintf (stderr, format, sFile, uLine); fputc('\n',stderr); fprintf (stderr, "root=%p,count=%d,pTmp=%p\n", pRememberRoot,count,pTmp); (void) fflush(stderr); DBUG_PRINT("safe",(format, sFile, uLine)); flag=1; Loading