summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
authorunknown <sasha@mysql.sashanet.com>2002-03-26 22:19:23 -0700
committerunknown <sasha@mysql.sashanet.com>2002-03-26 22:19:23 -0700
commit079a551ca735e79f3d7a2ebbecf8be4d4ba7608a (patch)
treeab4d73690dcb8e3ef54e70015f1838cf17a2577a /mysys
parent9c435716a9773f78cd5db0a992bd4b89b83bc25a (diff)
downloadmariadb-git-079a551ca735e79f3d7a2ebbecf8be4d4ba7608a.tar.gz
coverted my_thread_init() /end to use my_malloc()/my_free() to help track
down replication corruption dbug/dbug.c: fixed DBUG_ macros to not crash if my_thread_init() had not been called include/my_sys.h: keep track of shutdown, main, and signal threads for safemalloc mysys/my_static.h: keep track of thread in safemalloc blocks mysys/my_thr_init.c: use my_malloc()/my_free() in my_thread_init() mysys/safemalloc.c: keep track of threads do not fuss if main,signal, or shutdown thread still has allocated blocks when we call TERMINATE() as some blocks are freed later and there is no easy way to make TERMINATE() wait for those threads sql/mysqld.cc: keep track of signal, main, and shutdown threads
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;