threads / discuss / 75

active_cache leaks

Subject: active_cache leaks

## tl;dr

One message between Apr 17, 2005 and Apr 17, 2005.

replies: 0people: 1as markdown or json

Brad Roberts· Apr 17, 2005, 07:07 UTC · lore

Ok.. so there's been a couple attempts to patch the leak that were all wrong due to mixed memory management for that array. Here's a seed for discussion on how to plug that leak. Some would argue that it's not leaking enough to fix, but for those that want to turn git into a library, the lifetime of the cache could end up not being short any more, so it's worth discussing how to fix it.

The q&d fix in this patch isn't elegant, but gets the job done. More interesting could be to have the entry itself contain a state bit, though that wastes storage space.

Two basic changes:
1) introduce a set_active_cache() api and change all 'active_cache[i] = ce'
   calls to use it.
2) add a active_cache_malloced array to parallel the active_cache array.
I don't like #2, but see that q&d comment. :)

It's only lightly tested as I'm still trying to wrap my head around how to actually use git and git-pasky.

I was tempted to add a get_cache_entry api as well, so that nothing outside of read-cache.c touched active_cache directly, but that can come next.

Later, Brad

--- cache.h +++ cache.h 2005-04-16 23:08:37.000000000 -0700

@@ -88,6 +88,7 @@
 extern int read_cache(void);
 extern int write_cache(int newfd, struct cache_entry **cache, int entries);
 extern int cache_name_pos(const char *name, int namelen);
+extern int set_cache_entry(struct cache_entry *ce, int pos, int malloced_entry);
 extern int add_cache_entry(struct cache_entry *ce, int ok_to_add);
 extern int remove_file_from_cache(char *path);
 extern int cache_match_stat(struct cache_entry *ce, struct stat *st);
--- read-cache.c
+++ read-cache.c	2005-04-16 23:32:34.000000000 -0700
@@ -8,6 +8,7 @@
 
 const char *sha1_file_directory = NULL;
 struct cache_entry **active_cache = NULL;
+static int * active_cache_malloced = NULL;
 unsigned int active_nr = 0, active_alloc = 0;
 
 void usage(const char *err)
@@ -381,6 +382,15 @@
 	return ce_namelen(b) == len && !memcmp(a->name, b->name, len);
 }
 
+int set_cache_entry(struct cache_entry *ce, int pos, int malloced_entry)
+{
+	if (active_cache_malloced[pos])
+		free(active_cache[pos]);
+	active_cache[pos] = ce;
+	active_cache_malloced[pos] = malloced_entry;
+	return 0;
+}
+
 int add_cache_entry(struct cache_entry *ce, int ok_to_add)
 {
 	int pos;
@@ -389,7 +399,7 @@
 
 	/* existing match? Just replace it */
 	if (pos >= 0) {
-		active_cache[pos] = ce;
+		set_cache_entry(ce, pos, 0);
 		return 0;
 	}
 	pos = -pos-1;
@@ -414,13 +424,16 @@
 	if (active_nr == active_alloc) {
 		active_alloc = alloc_nr(active_alloc);
 		active_cache = realloc(active_cache, active_alloc * sizeof(struct cache_entry *));
+		active_cache_malloced = realloc(active_cache, active_alloc * sizeof(int));
 	}
 
 	/* Add it in.. */
 	active_nr++;
-	if (active_nr > pos)
+	if (active_nr > pos) {
 		memmove(active_cache + pos + 1, active_cache + pos, (active_nr - pos - 1) * sizeof(ce));
-	active_cache[pos] = ce;
+		memmove(active_cache_malloced + pos + 1, active_cache_malloced + pos, (active_nr - pos - 1) * sizeof(int));
+	}
+	set_cache_entry(ce, pos, 1);
 	return 0;
 }
 
@@ -482,12 +495,13 @@
 	active_nr = ntohl(hdr->hdr_entries);
 	active_alloc = alloc_nr(active_nr);
 	active_cache = calloc(active_alloc, sizeof(struct cache_entry *));
+	active_cache_malloced = calloc(active_alloc, sizeof(int));
 
 	offset = sizeof(*hdr);
 	for (i = 0; i < active_nr; i++) {
 		struct cache_entry *ce = map + offset;
 		offset = offset + ce_size(ce);
-		active_cache[i] = ce;
+		set_cache_entry(ce, i, 0);
 	}
 	return active_nr;
 
--- update-cache.c
+++ update-cache.c	2005-04-16 23:33:28.000000000 -0700
@@ -199,11 +199,14 @@
 		struct cache_entry *ce = active_cache[i];
 		struct cache_entry *new = refresh_entry(ce);
 
+		if (new == ce)
+			continue;
+
 		if (!new) {
 			printf("%s: needs update\n", ce->name);
 			continue;
 		}
-		active_cache[i] = new;
+		set_cache_entry(new, i, 1);
 	}
 }
 

← back to recent threads