From a337b58c154994e7644dd6b5e1928f06ee9d766e Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Wed, 24 Mar 2004 17:07:11 +0000 Subject: [PATCH] * Put a new memory leak checker into the server because it turns out that the third-party ones all suck. :) This one doesn't involve renaming all of the malloc() related functions, though. --- citadel/ChangeLog | 6 +- citadel/citserver.c | 4 ++ citadel/server.h | 1 + citadel/server_main.c | 1 - citadel/sysdep.c | 132 ++++++++++++++++++++++++++++++++++++++++- citadel/sysdep_decls.h | 22 +++++++ 6 files changed, 162 insertions(+), 4 deletions(-) diff --git a/citadel/ChangeLog b/citadel/ChangeLog index d2c7a1d27..0a949aef3 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -1,4 +1,9 @@ $Log$ + Revision 614.99 2004/03/24 17:07:11 ajc + * Put a new memory leak checker into the server because it turns out that + the third-party ones all suck. :) This one doesn't involve renaming + all of the malloc() related functions, though. + Revision 614.98 2004/03/24 15:04:06 ajc * stress.c: fix "wrong password" race condition by giving the very first worker thread time to finish creating the user account before the @@ -5604,4 +5609,3 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant Fri Jul 10 1998 Art Cancro * Initial CVS import - diff --git a/citadel/citserver.c b/citadel/citserver.c index 440137631..8fd945e5f 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -142,6 +142,10 @@ void master_cleanup(void) { /* Do system-dependent stuff */ sysdep_master_cleanup(); +#ifdef DEBUG_MEMORY_LEAKS + dump_heap(); +#endif + /* Now go away. */ lprintf(CTDL_NOTICE, "citserver: exiting.\n"); fflush(stdout); fflush(stderr); diff --git a/citadel/server.h b/citadel/server.h index c543de3b7..d1ec072c8 100644 --- a/citadel/server.h +++ b/citadel/server.h @@ -212,6 +212,7 @@ enum { S_PUBLIC_CLIENTS, S_LDAP, S_FLOORCACHE, + S_DEBUGMEMLEAKS, MAX_SEMAPHORES }; diff --git a/citadel/server_main.c b/citadel/server_main.c index e2872df5d..8e7849818 100644 --- a/citadel/server_main.c +++ b/citadel/server_main.c @@ -256,6 +256,5 @@ int main(int argc, char **argv) end_critical_section(S_WORKER_LIST); master_cleanup(); - return(0); } diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 4dc376679..99629d7f1 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -72,6 +72,19 @@ #include "snprintf.h" #endif + +#ifdef DEBUG_MEMORY_LEAKS +struct igheap { + struct igheap *next; + char file[32]; + int line; + void *block; +}; + +struct igheap *igheap = NULL; +#endif + + pthread_mutex_t Critters[MAX_SEMAPHORES]; /* Things needing locking */ pthread_key_t MyConKey; /* TSD key for MyContext() */ @@ -236,9 +249,17 @@ void init_sysdep(void) { void begin_critical_section(int which_one) { /* lprintf(CTDL_DEBUG, "begin_critical_section(%d)\n", which_one); */ + + /* ensure nobody ever tries to do a critical section within a - transaction; this could lead to deadlock. */ - cdb_check_handles(); + transaction; this could lead to deadlock. */ +#ifdef DEBUG_MEMORY_LEAKS + if (which_one != S_DEBUGMEMLEAKS) { +#endif + cdb_check_handles(); +#ifdef DEBUG_MEMORY_LEAKS + } +#endif pthread_mutex_lock(&Critters[which_one]); } @@ -1148,3 +1169,110 @@ int SyslogFacility(char *name) return -1; } + +/********** MEM CHEQQER ***********/ + +#ifdef DEBUG_MEMORY_LEAKS + +#undef malloc +#undef realloc +#undef strdup +#undef free + +void *tracked_malloc(size_t size, char *file, int line) { + struct igheap *thisheap; + void *block; + + block = malloc(size); + if (block == NULL) return(block); + + thisheap = malloc(sizeof(struct igheap)); + if (thisheap == NULL) { + free(block); + return(NULL); + } + + thisheap->block = block; + strcpy(thisheap->file, file); + thisheap->line = line; + + begin_critical_section(S_DEBUGMEMLEAKS); + thisheap->next = igheap; + igheap = thisheap; + end_critical_section(S_DEBUGMEMLEAKS); + + return(block); +} + + +void *tracked_realloc(void *ptr, size_t size, char *file, int line) { + struct igheap *thisheap; + void *block; + + block = realloc(ptr, size); + if (block == NULL) return(block); + + thisheap = malloc(sizeof(struct igheap)); + if (thisheap == NULL) { + free(block); + return(NULL); + } + + thisheap->block = block; + strcpy(thisheap->file, file); + thisheap->line = line; + + begin_critical_section(S_DEBUGMEMLEAKS); + thisheap->next = igheap; + igheap = thisheap; + end_critical_section(S_DEBUGMEMLEAKS); + + return(block); +} + + + +void tracked_free(void *ptr) { + struct igheap *thisheap; + struct igheap *trash; + + free(ptr); + + if (igheap == NULL) return; + begin_critical_section(S_DEBUGMEMLEAKS); + for (thisheap = igheap; thisheap != NULL; thisheap = thisheap->next) { + if (thisheap->next != NULL) { + if (thisheap->next->block == ptr) { + trash = thisheap->next; + thisheap->next = thisheap->next->next; + free(trash); + } + } + } + if (igheap->block == ptr) { + trash = igheap; + igheap = igheap->next; + free(trash); + } + end_critical_section(S_DEBUGMEMLEAKS); +} + +char *tracked_strdup(const char *s, char *file, int line) { + char *ptr; + + if (s == NULL) return(NULL); + ptr = tracked_malloc(strlen(s) + 1, file, line); + if (ptr == NULL) return(NULL); + strncpy(ptr, s, strlen(s)); + return(ptr); +} + +void dump_heap(void) { + struct igheap *thisheap; + + for (thisheap = igheap; thisheap != NULL; thisheap = thisheap->next) { + lprintf(CTDL_DEBUG, "%30s : %d\n", thisheap->file, thisheap->line); + } +} + +#endif /* DEBUG_MEMORY_LEAKS */ diff --git a/citadel/sysdep_decls.h b/citadel/sysdep_decls.h index a83c14816..008031e4a 100644 --- a/citadel/sysdep_decls.h +++ b/citadel/sysdep_decls.h @@ -1,5 +1,14 @@ /* $Id$ */ + +/* + * Uncomment this #define if you are a Citadel developer tracking + * down memory leaks in the server. Do NOT do this on a production + * system because it definitely incurs a lot of additional overhead. + */ +/* #define DEBUG_MEMORY_LEAKS */ + + #include #include "sysdep.h" #include "server.h" @@ -72,3 +81,16 @@ extern struct worker_node { extern int SyslogFacility(char *name); extern int syslog_facility; + +#ifdef DEBUG_MEMORY_LEAKS +#define malloc(x) tracked_malloc(x, __FILE__, __LINE__) +#define realloc(x,y) tracked_realloc(x, y, __FILE__, __LINE__) +#undef strdup +#define strdup(x) tracked_strdup(x, __FILE__, __LINE__) +#define free(x) tracked_free(x) +void *tracked_malloc(size_t size, char *file, int line); +void *tracked_realloc(void *ptr, size_t size, char *file, int line); +void tracked_free(void *ptr); +char *tracked_strdup(const char *s, char *file, int line); +void dump_heap(void); +#endif -- 2.39.2