From: Peter Stamfest Date: Wed, 12 Mar 2014 16:39:13 +0000 (+0100) Subject: Try to handle freeing of mmapped and malloced rrd_t objects transparently X-Git-Tag: v1.5.0-rc1~117^2~2^2~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1c42e106da2bd6e0ef2e3a27a12afc6b62b6b612;p=thirdparty%2Frrdtool-1.x.git Try to handle freeing of mmapped and malloced rrd_t objects transparently 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 --- diff --git a/src/rrd_format.h b/src/rrd_format.h index bb186fd8..b526a144 100644 --- a/src/rrd_format.h +++ b/src/rrd_format.h @@ -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; /**************************************************************************** diff --git a/src/rrd_open.c b/src/rrd_open.c index 7bc33e87..f9aeea2d 100644 --- a/src/rrd_open.c +++ b/src/rrd_open.c @@ -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 */