On Thu, 2015-10-15 at 05:35 +0200, René Scharfe wrote: > Am 15.10.2015 um 00:07 schrieb David Turner: > > From: Keith McGuigan <kmcguigan@xxxxxxxxxxx> > > > > During merges, we would previously free entries that we no longer need > > in the destination index. But those entries might also be stored in > > the dir_entry cache, and when a later call to add_to_index found them, > > they would be used after being freed. > > > > To prevent this, add a ref count for struct cache_entry. Whenever > > a cache entry is added to a data structure, the ref count is incremented; > > when it is removed from the data structure, it is decremented. When > > it hits zero, the cache_entry is freed. > > > > Signed-off-by: Keith McGuigan <kmcguigan@xxxxxxxxxxx> > > Signed-off-by: David Turner <dturner@xxxxxxxxxxxxxxxx> > > --- > > > > Fix type of ref_count (from unsigned int to int). > > > > > > cache.h | 27 +++++++++++++++++++++++++++ > > name-hash.c | 7 ++++++- > > read-cache.c | 6 +++++- > > split-index.c | 13 ++++++++----- > > unpack-trees.c | 6 ++++-- > > 5 files changed, 50 insertions(+), 9 deletions(-) > > > > diff --git a/cache.h b/cache.h > > index 752031e..7906026 100644 > > --- a/cache.h > > +++ b/cache.h > > @@ -149,6 +149,7 @@ struct stat_data { > > > > struct cache_entry { > > struct hashmap_entry ent; > > + int ref_count; /* count the number of refs to this in dir_hash */ > > struct stat_data ce_stat_data; > > unsigned int ce_mode; > > unsigned int ce_flags; > > @@ -213,6 +214,32 @@ struct cache_entry { > > struct pathspec; > > > > /* > > + * Increment the cache_entry reference count. Should be called > > + * whenever a pointer to a cache_entry is retained in a data structure, > > + * thus marking it as alive. > > + */ > > +static inline void add_ce_ref(struct cache_entry *ce) > > +{ > > + assert(ce != NULL && ce->ref_count >= 0); > > + ce->ref_count++; > > +} > > + > > +/* > > + * Decrement the cache_entry reference count. Should be called whenever > > + * a pointer to a cache_entry is dropped. Once the counter drops to 0 > > + * the cache_entry memory will be safely freed. > > + */ > > +static inline void drop_ce_ref(struct cache_entry *ce) > > +{ > > + if (ce != NULL) { > > + assert(ce->ref_count >= 0); > > Shouldn't this be "> 0" to prevent double frees? No. If the ref_count is 1, then there is still some reference to the ce. If it is 0, there is no reference to it, and the next check (< 1) will succeed and the ce will get freed. > > + if (--ce->ref_count < 1) { > > + free(ce); > > + } > > + } > > +} > -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html