From: oetiker Date: Wed, 22 Oct 2008 06:02:23 +0000 (+0000) Subject: remove_cache_item() did not check whether a file was in queue before X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=7da84b6fd796d774d5db4aefb6615d33fa2711b4;p=rrdtool.git remove_cache_item() did not check whether a file was in queue before modifying the cache head/tail pointers. Therefore, the process of flushing old files may perturb the cache_queue_head pointer. This caused some nodes with CI_FLAGS_IN_QUEUE to be un-linked from the queue list. Thereafter, they would not be flushed by any periodic process (although they could be revived with FLUSH or UPDATE). This caused a slow memory leak for files that are no longer updated. Pending updates for these "abandoned" files would remain in memory ad infinitum. With this patch, remove_from_queue() will check that the item is queued before modifying the head/tail pointers. This restores the intended behavior. --kevin git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1626 a5681a0c-68f1-0310-ab6d-d61299d08faa --- diff --git a/src/rrd_daemon.c b/src/rrd_daemon.c index d404e04..8d26e0a 100644 --- a/src/rrd_daemon.c +++ b/src/rrd_daemon.c @@ -564,6 +564,7 @@ static void wipe_ci_values(cache_item_t *ci, time_t when) static void remove_from_queue(cache_item_t *ci) /* {{{ */ { if (ci == NULL) return; + if ((ci->flags & CI_FLAGS_IN_QUEUE) == 0) return; /* not queued */ if (ci->prev == NULL) cache_queue_head = ci->next; /* reset head */ @@ -625,9 +626,8 @@ static int enqueue_cache_item (cache_item_t *ci, /* {{{ */ if (cache_queue_head == ci) return 0; - /* remove from the double linked list */ - if (ci->flags & CI_FLAGS_IN_QUEUE) - remove_from_queue(ci); + /* remove if further down in queue */ + remove_from_queue(ci); ci->prev = NULL; ci->next = cache_queue_head; @@ -681,20 +681,20 @@ static gboolean tree_callback_flush (gpointer key, gpointer value, /* {{{ */ ci = (cache_item_t *) value; cfd = (callback_flush_data_t *) data; + if (ci->flags & CI_FLAGS_IN_QUEUE) + return FALSE; + if ((ci->last_flush_time <= cfd->abs_timeout) - && ((ci->flags & CI_FLAGS_IN_QUEUE) == 0) && (ci->values_num > 0)) { enqueue_cache_item (ci, TAIL); } else if ((do_shutdown != 0) - && ((ci->flags & CI_FLAGS_IN_QUEUE) == 0) && (ci->values_num > 0)) { enqueue_cache_item (ci, TAIL); } else if (((cfd->now - ci->last_flush_time) >= config_flush_interval) - && ((ci->flags & CI_FLAGS_IN_QUEUE) == 0) && (ci->values_num <= 0)) { char **temp;