Commit 649214be4bd9d8239787e3af7e6d877955d09e11

Carlos Martín Nieto 2014-05-15T19:59:05

pack: init the cache on packfile alloc When running multithreaded, it is not enough to check for the offmap allocation. Move the call to cache_init() to packfile allocation so we can be sure it is always allocated free of races. This fixes #2355.

diff --git a/src/pack.c b/src/pack.c
index d93ee25..ace7abb 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -83,16 +83,12 @@ static void cache_free(git_pack_cache *cache)
 		}
 
 		git_offmap_free(cache->entries);
-		git_mutex_free(&cache->lock);
+		cache->entries = NULL;
 	}
-
-	memset(cache, 0, sizeof(*cache));
 }
 
 static int cache_init(git_pack_cache *cache)
 {
-	memset(cache, 0, sizeof(*cache));
-
 	cache->entries = git_offmap_alloc();
 	GITERR_CHECK_ALLOC(cache->entries);
 
@@ -534,9 +530,6 @@ static int pack_dependency_chain(git_dependency_chain *chain_out,
 	size_t size, elem_pos;
 	git_otype type;
 
-	if (!p->bases.entries && (cache_init(&p->bases) < 0))
-		return -1;
-
 	elem_pos = 0;
 	while (true) {
 		struct pack_chain_elem *elem;
@@ -985,6 +978,7 @@ void git_packfile_free(struct git_pack_file *p)
 	git__free(p->bad_object_sha1);
 
 	git_mutex_free(&p->lock);
+	git_mutex_free(&p->bases.lock);
 	git__free(p);
 }
 
@@ -1120,6 +1114,11 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
 		return -1;
 	}
 
+	if (cache_init(&p->bases) < 0) {
+		git__free(p);
+		return -1;
+	}
+
 	*pack_out = p;
 
 	return 0;