Commit 8303827226db114a1157e6173e731f316c217851

Russell Belfer 2014-04-17T14:35:29

Some memory leak fixes

diff --git a/src/attrcache.c b/src/attrcache.c
index 925abb5..88b68eb 100644
--- a/src/attrcache.c
+++ b/src/attrcache.c
@@ -121,7 +121,6 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file)
 {
 	int error = 0;
 	git_attr_file_entry *entry;
-	bool found = false;
 
 	if (!file)
 		return 0;
@@ -133,7 +132,7 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file)
 
 	attr_cache_unlock(cache);
 
-	if (found) {
+	if (file) {
 		GIT_REFCOUNT_OWN(file, NULL);
 		git_attr_file__free(file);
 	}
@@ -206,39 +205,42 @@ int git_attr_cache__get(
 	int error = 0;
 	git_attr_cache *cache = git_repository_attr_cache(repo);
 	git_attr_file_entry *entry = NULL;
-	git_attr_file *file = NULL;
+	git_attr_file *file = NULL, *updated = NULL;
 
 	if ((error = attr_cache_lookup(
 			&file, &entry, repo, source, base, filename)) < 0)
-		goto cleanup;
-
-	/* if file not found or out of date, load up-to-date data and replace */
-	if (!file || (error = git_attr_file__out_of_date(repo, file)) > 0) {
-		/* decrement refcount (if file was found) b/c we will not return it */
-		git_attr_file__free(file);
+		return error;
 
-		if (!(error = git_attr_file__load(&file, repo, entry, source, parser)))
-			error = attr_cache_upsert(cache, file);
+	/* load file if we don't have one or if existing one is out of date */
+	if (!file || (error = git_attr_file__out_of_date(repo, file)) > 0)
+		error = git_attr_file__load(&updated, repo, entry, source, parser);
+
+	/* if we loaded the file, insert into and/or update cache */
+	if (updated) {
+		if ((error = attr_cache_upsert(cache, updated)) < 0)
+			git_attr_file__free(updated);
+		else {
+			git_attr_file__free(file); /* offset incref from lookup */
+			file = updated;
+		}
 	}
 
-	/* GIT_ENOTFOUND is okay when probing for the file.  If the file did
-	 * exist and now does not, we have to remove it from cache, however.
-	 */
-	if (error == GIT_ENOTFOUND) {
-		giterr_clear();
-		error = 0;
-
-		if (file != NULL)
-			error = attr_cache_remove(cache, file);
+	/* if file could not be loaded */
+	if (error < 0) {
+		/* remove existing entry */
+		if (file) {
+			git_attr_file__free(file); /* offset incref from lookup */
+			attr_cache_remove(cache, file);
+			file = NULL;
+		}
+		/* no error if file simply doesn't exist */
+		if (error == GIT_ENOTFOUND) {
+			giterr_clear();
+			error = 0;
+		}
 	}
 
-cleanup:
-	if (error < 0 && file != NULL) {
-		git_attr_file__free(file);
-		file = NULL;
-	}
 	*out = file;
-
 	return error;
 }
 
diff --git a/tests/threads/diff.c b/tests/threads/diff.c
index d33e75f..79b8580 100644
--- a/tests/threads/diff.c
+++ b/tests/threads/diff.c
@@ -103,6 +103,7 @@ static void *run_index_diffs(void *arg)
 	}
 
 	git_diff_free(diff);
+	giterr_clear();
 
 	return arg;
 }
@@ -139,8 +140,7 @@ static void *run_index_diffs_with_modifier(void *arg)
 			git_thread_yield();
 		}
 
-		git_index_free(idx);
-		return arg;
+		goto done;
 	}
 
 	/* only use explicit index in this test to prevent reloading */
@@ -164,7 +164,10 @@ static void *run_index_diffs_with_modifier(void *arg)
 	/* results will be unpredictable with index modifier thread running */
 
 	git_diff_free(diff);
+
+done:
 	git_index_free(idx);
+	giterr_clear();
 
 	return arg;
 }
diff --git a/tests/threads/iterator.c b/tests/threads/iterator.c
index 4dd251f..8aeae1a 100644
--- a/tests/threads/iterator.c
+++ b/tests/threads/iterator.c
@@ -11,7 +11,7 @@ void test_threads_iterator__cleanup(void)
 
 static void *run_workdir_iterator(void *arg)
 {
-	int error = 0, thread = *(int *)arg;
+	int error = 0;
 	git_iterator *iter;
 	const git_index_entry *entry = NULL;
 
@@ -35,7 +35,7 @@ static void *run_workdir_iterator(void *arg)
 	cl_assert_equal_i(GIT_ITEROVER, error);
 
 	git_iterator_free(iter);
-
+	giterr_clear();
 	return arg;
 }
 
diff --git a/tests/threads/refdb.c b/tests/threads/refdb.c
index fbf6ac0..3b35b45 100644
--- a/tests/threads/refdb.c
+++ b/tests/threads/refdb.c
@@ -37,6 +37,7 @@ static void *iterate_refs(void *arg)
 
 	git_reference_iterator_free(i);
 
+	giterr_clear();
 	return arg;
 }
 
@@ -115,6 +116,7 @@ static void *create_refs(void *arg)
 	for (i = 0; i < 10; ++i)
 		git_reference_free(ref[i]);
 
+	giterr_clear();
 	return arg;
 }
 
@@ -141,6 +143,7 @@ static void *delete_refs(void *arg)
 		}
 	}
 
+	giterr_clear();
 	return arg;
 }