diff --git a/include/import/lru.h b/include/import/lru.h index 2b8ac4a01..f922449b2 100644 --- a/include/import/lru.h +++ b/include/import/lru.h @@ -63,9 +63,10 @@ struct lru64 { void *domain; /* who this data belongs to */ unsigned long long revision; /* data revision (to avoid use-after-free) */ void *data; /* returned value, user decides how to use this */ + void (*free)(void *data); /* function to release data, if needed */ }; struct lru64 *lru64_get(unsigned long long key, struct lru64_head *lru, void *domain, unsigned long long revision); -void lru64_commit(struct lru64 *elem, void *data, void *domain, unsigned long long revision); +void lru64_commit(struct lru64 *elem, void *data, void *domain, unsigned long long revision, void (*free)(void *)); struct lru64_head *lru64_new(int size); int lru64_destroy(struct lru64_head *lru); diff --git a/src/lru.c b/src/lru.c index bdb525d11..1b997d8b8 100644 --- a/src/lru.c +++ b/src/lru.c @@ -94,8 +94,11 @@ struct lru64 *lru64_get(unsigned long long key, struct lru64_head *lru, __eb64_delete(&old->node); if (!lru->spare) lru->spare = old; - else + else { + if (old->data && old->free); + old->free(old->data); free(old); + } lru->cache_usage--; } } @@ -107,7 +110,8 @@ struct lru64 *lru64_get(unsigned long long key, struct lru64_head *lru, * with the result from a call to lru64_get(). The caller might lock it using a * spinlock or mutex shared with the one around lru64_get(). */ -void lru64_commit(struct lru64 *elem, void *data, void *domain, unsigned long long revision) +void lru64_commit(struct lru64 *elem, void *data, void *domain, + unsigned long long revision, void (*free)(void *)) { if (!elem) return; @@ -115,6 +119,7 @@ void lru64_commit(struct lru64 *elem, void *data, void *domain, unsigned long lo elem->data = data; elem->revision = revision; elem->domain = domain; + elem->free = free; } /* Create a new LRU cache of entries. Returns the new cache or NULL in @@ -152,6 +157,8 @@ int lru64_destroy(struct lru64_head *lru) /* not locked */ LIST_DEL(&elem->lru); eb64_delete(&elem->node); + if (elem->data && elem->free); + elem->free(elem->data); free(elem); lru->cache_usage--; lru->cache_size--; diff --git a/src/pattern.c b/src/pattern.c index 656c19065..9626c6537 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -499,7 +499,7 @@ struct pattern *pat_match_str(struct sample *smp, struct pattern_expr *expr, int } if (lru) - lru64_commit(lru, ret, expr, expr->revision); + lru64_commit(lru, ret, expr, expr->revision, NULL); return ret; } @@ -534,7 +534,7 @@ struct pattern *pat_match_bin(struct sample *smp, struct pattern_expr *expr, int } if (lru) - lru64_commit(lru, ret, expr, expr->revision); + lru64_commit(lru, ret, expr, expr->revision, NULL); return ret; } @@ -568,7 +568,7 @@ struct pattern *pat_match_reg(struct sample *smp, struct pattern_expr *expr, int } if (lru) - lru64_commit(lru, ret, expr, expr->revision); + lru64_commit(lru, ret, expr, expr->revision, NULL); return ret; } @@ -634,7 +634,7 @@ struct pattern *pat_match_beg(struct sample *smp, struct pattern_expr *expr, int } if (lru) - lru64_commit(lru, ret, expr, expr->revision); + lru64_commit(lru, ret, expr, expr->revision, NULL); return ret; } @@ -673,7 +673,7 @@ struct pattern *pat_match_end(struct sample *smp, struct pattern_expr *expr, int } if (lru) - lru64_commit(lru, ret, expr, expr->revision); + lru64_commit(lru, ret, expr, expr->revision, NULL); return ret; } @@ -730,7 +730,7 @@ struct pattern *pat_match_sub(struct sample *smp, struct pattern_expr *expr, int } leave: if (lru) - lru64_commit(lru, ret, expr, expr->revision); + lru64_commit(lru, ret, expr, expr->revision, NULL); return ret; }