summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
authorsasha@mysql.sashanet.com <>2002-03-26 22:19:23 -0700
committersasha@mysql.sashanet.com <>2002-03-26 22:19:23 -0700
commitf28f8d086d3f5e1ede685b86ce64da5641437bcf (patch)
treeab4d73690dcb8e3ef54e70015f1838cf17a2577a /mysys
parent2e6b48afd31008809439900db2d577ea0ff9d90f (diff)
downloadmariadb-git-f28f8d086d3f5e1ede685b86ce64da5641437bcf.tar.gz
coverted my_thread_init() /end to use my_malloc()/my_free() to help track
down replication corruption
Diffstat (limited to 'mysys')
-rw-r--r--mysys/my_static.h6
-rw-r--r--mysys/my_thr_init.c39
-rw-r--r--mysys/safemalloc.c70
3 files changed, 109 insertions, 6 deletions
diff --git a/mysys/my_static.h b/mysys/my_static.h
index 4f944938b8d..ca384009063 100644
--- a/mysys/my_static.h
+++ b/mysys/my_static.h
@@ -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 */
};
@@ -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
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index b4d98feeeb6..2c7fd098c63 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -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;
@@ -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)
@@ -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);
@@ -160,12 +186,15 @@ void my_thread_end(void)
#endif
pthread_mutex_destroy(&tmp->mutex);
#if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS)
- free(tmp);
+ /* 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
}
-#if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS)
- pthread_setspecific(THR_KEY_mysys,0);
-#endif
}
struct st_my_thread_var *_my_thread_var(void)
diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c
index d8c089c2ff0..062f9b9db02 100644
--- a/mysys/safemalloc.c
+++ b/mysys/safemalloc.c
@@ -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,
@@ -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 */
@@ -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)
@@ -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)
@@ -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",
@@ -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);
@@ -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;