Author: ivan
Date: Tue Nov  3 15:01:07 2015
New Revision: 1712305

URL: http://svn.apache.org/viewvc?rev=1712305&view=rev
Log:
Checkpoint basic tracking of unfreed memory blocks in bucket allocator.

Tracking is enabled at compile-time using SERF__DEBUG_UNFREED_MEMORY macro
in buckets/allocator.c

* buckets/allocator.c
  (): Include apr_hash.h and apr_strings.h.
  (SERF__DEBUG_UNFREED_MEMORY): Add, but comment by default.
  (serf_bucket_alloc_t): Add UNFREED_BLOCKS hashtable if
   SERF__DEBUG_UNFREED_MEMORY is defined.
  (allocator_cleanup): Dump unfreed memory blocks using fprint() or unfreed
   callback if SERF__DEBUG_UNFREED_MEMORY is defined.
  (serf_bucket_allocator_create): Initialize UNFREED_BLOCKS hashtable if
   SERF__DEBUG_UNFREED_MEMORY is defined.
  (serf_bucket_mem_alloc, serf_bucket_mem_free): Track allocated blocks if
   SERF__DEBUG_UNFREED_MEMORY is defined.

Modified:
    serf/trunk/buckets/allocator.c

Modified: serf/trunk/buckets/allocator.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/allocator.c?rev=1712305&r1=1712304&r2=1712305&view=diff
==============================================================================
--- serf/trunk/buckets/allocator.c (original)
+++ serf/trunk/buckets/allocator.c Tue Nov  3 15:01:07 2015
@@ -23,12 +23,17 @@
 #define APR_WANT_MEMFUNC
 #include <apr_want.h>
 #include <apr_pools.h>
+#include <apr_hash.h>
+#include <apr_strings.h>
 
 #include "serf.h"
 #include "serf_bucket_util.h"
 
 #include "serf_private.h"
 
+/* Define SERF__DEBUG_UNFREED_MEMORY if you're interested in tracking
+ * unfreed blocks on pool cleanup. */
+/* #define SERF__DEBUG_UNFREED_MEMORY */
 
 typedef struct node_header_t {
     apr_size_t size;
@@ -106,6 +111,10 @@ struct serf_bucket_alloc_t {
     apr_memnode_t *blocks;      /* blocks we allocated for subdividing */
 
     track_state_t *track;
+
+#ifdef SERF__DEBUG_UNFREED_MEMORY
+    apr_hash_t *unfreed_blocks;
+#endif
 };
 
 /* ==================================================================== */
@@ -115,6 +124,23 @@ static apr_status_t allocator_cleanup(vo
 {
     serf_bucket_alloc_t *allocator = data;
 
+#ifdef SERF__DEBUG_UNFREED_MEMORY
+    apr_hash_index_t *hi;
+    for (hi = apr_hash_first(NULL, allocator->unfreed_blocks);
+         hi; hi = apr_hash_next(hi))
+    {
+        void **block_p = (void**) apr_hash_this_key(hi);
+        apr_size_t size = (apr_size_t) apr_hash_this_val(hi);
+
+        if (allocator->unfreed) {
+            allocator->unfreed(allocator->unfreed_baton, *block_p);
+        }
+        else {
+            fprintf(stderr, "Unfreed memory: %p (%d bytes)\n", *block_p, size);
+        }
+    }
+#endif
+
     /* If we allocated anything, give it back. */
     if (allocator->blocks) {
         apr_allocator_free(allocator->allocator, allocator->blocks);
@@ -148,6 +174,10 @@ serf_bucket_alloc_t *serf_bucket_allocat
     allocator->unfreed = unfreed;
     allocator->unfreed_baton = unfreed_baton;
 
+#ifdef SERF__DEBUG_UNFREED_MEMORY
+    allocator->unfreed_blocks = apr_hash_make(pool);
+#endif
+
 #ifdef SERF_DEBUG_BUCKET_USE
     {
         track_state_t *track;
@@ -182,6 +212,7 @@ void *serf_bucket_mem_alloc(
     apr_size_t size)
 {
     node_header_t *node;
+    void *block;
 
     ++allocator->num_alloc;
 
@@ -235,7 +266,15 @@ void *serf_bucket_mem_alloc(
         node->size = size;
     }
 
-    return ((char *)node) + SIZEOF_NODE_HEADER_T;
+    block = ((char *)node) + SIZEOF_NODE_HEADER_T;
+
+#ifdef SERF__DEBUG_UNFREED_MEMORY
+    apr_hash_set(allocator->unfreed_blocks,
+                 apr_pmemdup(allocator->pool, &block, sizeof(block)),
+                 sizeof(block), (const void*) size);
+#endif
+
+    return block;
 }
 
 
@@ -285,6 +324,11 @@ void serf_bucket_mem_free(
         /* now free it */
         apr_allocator_free(allocator->allocator, node->u.memnode);
     }
+
+#ifdef SERF__DEBUG_UNFREED_MEMORY
+    /* Remove block from unfreed blocks hashtable. */
+    apr_hash_set(allocator->unfreed_blocks, &block, sizeof(block), NULL);
+#endif
 }
 
 


Reply via email to