Hi together,

please find attached patch that adds support for glibc malloc hooks and so
make it possible to debug memory problems in external libraries.

Comments?

-- 
Thanks,
Alex
Index: gwlib/thread.h
===================================================================
RCS file: /home/cvs/gateway/gwlib/thread.h,v
retrieving revision 1.23
diff -a -u -p -r1.23 thread.h
--- gwlib/thread.h	22 Jan 2004 14:08:25 -0000	1.23
+++ gwlib/thread.h	2 Feb 2005 17:04:02 -0000
@@ -85,6 +85,25 @@ typedef struct {
 #endif
 } Mutex;
 
+#ifdef MUTEX_STATS
+#define GW_MUTEX_INITIALIZER            \
+{                                       \
+    .mutex = PTHREAD_MUTEX_INITIALIZER, \
+    .owner = -1,                        \
+    .dynamic = 0,                       \
+    .filename = __FILE__,               \
+    .lineno = __LINE__,                 \
+    .locks = 0,                         \
+    .collisions = 0,                    \
+}
+#else
+#define GW_MUTEX_INITIALIZER            \
+{                                       \
+    .mutex = PTHREAD_MUTEX_INITIALIZER, \
+    .owner = -1,                        \
+    .dynamic = 0,                       \
+}
+#endif
 
 /*
  * Create a Mutex.
Index: gwlib/gwmem-check.c
===================================================================
RCS file: /home/cvs/gateway/gwlib/gwmem-check.c,v
retrieving revision 1.27
diff -a -u -p -r1.27 gwmem-check.c
--- gwlib/gwmem-check.c	21 Jan 2005 13:50:46 -0000	1.27
+++ gwlib/gwmem-check.c	2 Feb 2005 17:04:02 -0000
@@ -131,7 +131,7 @@ static int slow = 0;
 /* We have to use a static mutex here, because otherwise the mutex_create
  * call would try to allocate memory with gw_malloc before we're
  * initialized. */
-static Mutex gwmem_lock;
+static Mutex gwmem_lock = GW_MUTEX_INITIALIZER;
 
 struct location
 {
@@ -192,6 +192,76 @@ static long highest_total_size;
 /* Current sum of allocated areas */
 static long total_size;
 
+
+/* glibc malloc debugging */
+#ifdef __GLIBC__
+#include <malloc.h>
+static void *gw_check_malloc_hook(size_t, const void*);
+static void gw_check_free_hook(void*, const void*);
+static void *gw_check_realloc_hook(void*, size_t, const void*);
+static void switch_to_gw_hook(void);
+static void init_gw_hook(void);
+
+static void *(*old_malloc_hook)(size_t, const void*);
+static void (*old_free_hook)(void*, const void*);
+static void *(*old_realloc_hook)(void*, size_t, const void*);
+
+void (*__malloc_initialize_hook)(void) = init_gw_hook;
+
+static pthread_mutex_t hook_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static void init_gw_hook(void)
+{
+    gw_check_init_mem(1);
+    old_malloc_hook = __malloc_hook;
+    __malloc_hook = gw_check_malloc_hook;
+    old_free_hook = __free_hook;
+    __free_hook = gw_check_free_hook;
+    old_realloc_hook = __realloc_hook;
+    __realloc_hook = gw_check_realloc_hook;
+}
+
+static void switch_to_gw_hook(void)
+{
+    old_malloc_hook = __malloc_hook;
+    __malloc_hook = gw_check_malloc_hook;
+    old_free_hook = __free_hook;
+    __free_hook = gw_check_free_hook;
+    old_realloc_hook = __realloc_hook;
+    __realloc_hook = gw_check_realloc_hook;
+    pthread_mutex_unlock(&hook_lock);
+}
+
+static void switch_to_glibc_hook(void)
+{
+    pthread_mutex_lock(&hook_lock);
+    /* restore old hoocks */
+    __malloc_hook = old_malloc_hook;
+    __free_hook = old_free_hook;
+    __realloc_hook = old_realloc_hook;
+}
+
+
+static void *gw_check_malloc_hook(size_t size, const void *caller)
+{
+    return gw_check_malloc(size, "?", 0, "?");
+}
+
+static void gw_check_free_hook(void *p, const void *caller)
+{
+    gw_check_free(p, "?", 0, "?");
+}
+
+static void *gw_check_realloc_hook(void *ptr, size_t size, const void *caller)
+{
+    return gw_check_realloc(ptr, size, "?", 0, "?");
+}
+#else
+#define switch_to_glibc_hook() do{}while(0)
+#define switch_to_gw_hook() do{}while(0)
+#endif /* __GLIBC__ */
+
+
 /* Static functions */
 
 static inline void lock(void)
@@ -341,7 +411,10 @@ static void dump_area(struct area *area)
 #if HAVE_BACKTRACE
     {
         size_t i;
-        char **strings = backtrace_symbols(area->frames, area->frame_size);
+        char **strings;
+        switch_to_glibc_hook();
+        strings = backtrace_symbols(area->frames, area->frame_size);
+        switch_to_gw_hook();
         debug("gwlib.gwmem", 0, "Backtrace of last malloc/realloc:");
         for (i = 0; i < area->frame_size; i++) {
             if (strings != NULL)
@@ -349,7 +422,9 @@ static void dump_area(struct area *area)
             else
                 debug("gwlib.gwmem", 0, "%p", area->frames[i]);
         }
+        switch_to_glibc_hook();
         free(strings);
+        switch_to_gw_hook();
     }
 #endif
 }
@@ -415,7 +490,7 @@ static void change_total_size(long chang
 }
 
 static struct area *record_allocation(unsigned char *p, size_t size,
-                                                  const char *filename, long lineno, const char *function)
+                                      const char *filename, long lineno, const char *function)
 {
     struct area *area;
     static struct area empty_area;
@@ -433,7 +508,9 @@ static struct area *record_allocation(un
     area->allocator.lineno = lineno;
     area->allocator.function = function;
 #if HAVE_BACKTRACE
+    switch_to_glibc_hook();
     area->frame_size = backtrace(area->frames, sizeof(area->frames) / sizeof(void*));
+    switch_to_gw_hook();
 #endif
 
     startmark(area->area, num_allocations);
@@ -468,7 +545,9 @@ static void drop_from_free_ring(long ind
         error(0, "Freed area %p has been tampered with.", area->area);
         dump_area(area);
     }
+    switch_to_glibc_hook();
     free((unsigned char *)area->area - MARKER_SIZE);
+    switch_to_gw_hook();
 }
 
 static void put_on_free_ring(struct area *area)
@@ -499,15 +578,12 @@ static void free_area(struct area *area)
 
 void gw_check_init_mem(int slow_flag)
 {
-    mutex_init_static(&gwmem_lock);
     slow = slow_flag;
     initialized = 1;
 }
 
 void gw_check_shutdown(void)
 {
-    mutex_destroy(&gwmem_lock);
-    initialized = 0;
 }
 
 void *gw_check_malloc(size_t size, const char *filename, long lineno,
@@ -520,7 +596,9 @@ void *gw_check_malloc(size_t size, const
     /* ANSI C89 says malloc(0) is implementation-defined.  Avoid it. */
     gw_assert(size > 0);
 
+    switch_to_glibc_hook();
     p = malloc(size + 2 * MARKER_SIZE);
+    switch_to_gw_hook();
     if (p == NULL)
         panic(errno, "Memory allocation of %d bytes failed.", size);
     p += MARKER_SIZE;
@@ -567,7 +645,9 @@ void *gw_check_realloc(void *p, size_t s
         unsigned char *new_p;
 
         new_size = round_pow2(size + 2 * MARKER_SIZE);
+        switch_to_glibc_hook();
         new_p = malloc(new_size);
+        switch_to_gw_hook();
         new_size -= 2 * MARKER_SIZE;
         new_p += MARKER_SIZE;
         memcpy(new_p, p, area->area_size);

Reply via email to