]> git.ipfire.org Git - thirdparty/rrdtool-1.x.git/commitdiff
Try to handle freeing of mmapped and malloced rrd_t objects transparently
authorPeter Stamfest <peter@stamfest.at>
Wed, 12 Mar 2014 16:39:13 +0000 (17:39 +0100)
committerPeter Stamfest <peter@stamfest.at>
Fri, 14 Mar 2014 06:35:04 +0000 (07:35 +0100)
This IS rather hackish - an OO inspired approach might be better, but adding
knowledge about mmapped memory to the free path even allows mixed
mmapped/malloced objects

src/rrd_format.h
src/rrd_open.c

index bb186fd8178f0cd1810cf85d93dcc1295b3bf110..b526a1448c8da31841dcac40de4b078af4c7d0d3 100644 (file)
@@ -404,6 +404,8 @@ typedef struct rrd_t {
     cdp_prep_t *cdp_prep;   /* cdp prep area */
     rra_ptr_t *rra_ptr; /* list of rra pointers */
     rrd_value_t *rrd_value; /* list of rrd values */
+    void *__mmap_start;            /* all __ variables will be used internally */
+    long __mmap_size;
 } rrd_t;
 
 /****************************************************************************
index 7bc33e87b287066b9a45b987e8409e127b7c596c..f9aeea2d5af245cbf8d9a9c9fbd562d7ac090698 100644 (file)
@@ -299,6 +299,9 @@ rrd_file_t *rrd_open(
                       rrd_strerror(errno));
         goto out_close;
     }
+    rrd->__mmap_start = data;
+    rrd->__mmap_size  = rrd_file->file_len;
+           
     rrd_simple_file->file_start = data;
 #endif
     if (rdwr & RRD_CREAT)
@@ -414,6 +417,8 @@ rrd_file_t *rrd_open(
 #ifdef HAVE_MMAP
     if (data != MAP_FAILED)
       munmap(data, rrd_file->file_len);
+    rrd->__mmap_start = NULL;
+    rrd->__mmap_size = 0;
 #endif
 
     close(rrd_simple_file->fd);
@@ -747,34 +752,44 @@ void rrd_init(
     rrd->pdp_prep = NULL;
     rrd->cdp_prep = NULL;
     rrd->rrd_value = NULL;
+    rrd->__mmap_start = NULL;
+    rrd->__mmap_size = 0;
 }
 
 
-/* free RRD header data.  */
-
-#ifdef HAVE_MMAP
-void rrd_free(
-    rrd_t *rrd)
+/* free RRD data, act correctly, regardless of mmap'ped or malloc'd memory. */
+static void free_rrd_ptr_if_not_mmapped(void *m, const rrd_t *rrd)
 {
-    if (rrd->legacy_last_up) {  /* this gets set for version < 3 only */
-        free(rrd->live_head);
+    if (m == NULL) return;
+    
+    if (rrd == NULL || rrd->__mmap_start == NULL) {
+       free(m);
+    }
+    
+    /* is this ALWAYS correct on all supported platforms ??? */
+    long ofs = (char*)m - (char*)rrd->__mmap_start;
+    if (ofs < rrd->__mmap_size) {
+       // DO NOT FREE, this memory is mmapped!!
+       return;
     }
+    
+    free(m);
 }
-#else
+
 void rrd_free(
     rrd_t *rrd)
 {
-    free(rrd->live_head);
-    free(rrd->stat_head);
-    free(rrd->ds_def);
-    free(rrd->rra_def);
-    free(rrd->rra_ptr);
-    free(rrd->pdp_prep);
-    free(rrd->cdp_prep);
-    free(rrd->rrd_value);
+    if (rrd == NULL) return;
+    
+    free_rrd_ptr_if_not_mmapped(rrd->live_head, rrd);
+    free_rrd_ptr_if_not_mmapped(rrd->stat_head, rrd);
+    free_rrd_ptr_if_not_mmapped(rrd->ds_def, rrd);
+    free_rrd_ptr_if_not_mmapped(rrd->rra_def, rrd);
+    free_rrd_ptr_if_not_mmapped(rrd->rra_ptr, rrd);
+    free_rrd_ptr_if_not_mmapped(rrd->pdp_prep, rrd);
+    free_rrd_ptr_if_not_mmapped(rrd->cdp_prep, rrd);
+    free_rrd_ptr_if_not_mmapped(rrd->rrd_value, rrd);
 }
-#endif
-
 
 /* routine used by external libraries to free memory allocated by
  * rrd library */