Subject: [PATCH 1/2] Introduce leaky().

From: Pierre Habouzit <[email-masked]>
Date: Tue, 24 Jun 2008 22:14:33 +0200

This can be used to mark allocated memory as a "leak". This can be used to
collect memory at the exit of the command, so that tools like valgrind can
be used to check for actual memory leak without noise.

COLLECT_LEAKS_AT_EXIT must be set to that purpose, else 'leaky' is the
transparent macro.

Signed-off-by: Pierre Habouzit <[email-masked]>
---
 Makefile |    5 +++++
 alloc.c  |   20 ++++++++++++++++++++
 cache.h  |    5 +++++
 3 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile
index 9c16482..6be15c8 100644
--- a/Makefile
+++ b/Makefile
@@ -151,6 +151,8 @@ all::
 # Define NO_EXTERNAL_GREP if you don't want "git grep" to ever call
 # your external grep (e.g., if your system lacks grep, if its grep is
 # broken, or spawning external process is slower than built-in grep git has).
+#
+# Define COLLECT_LEAKS_AT_EXIT if you want memory marked as leaky() at exit.
 
 GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
 	@$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -947,6 +949,9 @@ endif
 ifdef NO_EXTERNAL_GREP
 	BASIC_CFLAGS += -DNO_EXTERNAL_GREP
 endif
+ifdef COLLECT_LEAKS_AT_EXIT
+	BASIC_CFLAGS += -DCOLLECT_LEAKS_AT_EXIT
+endif
 
 ifeq ($(TCLTK_PATH),)
 NO_TCLTK=NoThanks
diff --git a/alloc.c b/alloc.c
index 216c23a..1afe810 100644
--- a/alloc.c
+++ b/alloc.c
@@ -74,3 +74,23 @@ void alloc_report(void)
 	REPORT(commit);
 	REPORT(tag);
 }
+
+#ifdef COLLECT_LEAKS_AT_EXIT
+static void **leaks;
+int leaknb, leaksz;
+
+static void release_leaks(void)
+{
+	while (leaknb-- > 0)
+		free(*leaks++);
+	free(leaks);
+}
+
+void *leaky(void *ptr)
+{
+	if (leaksz == 0)
+		atexit(&release_leaks);
+	ALLOC_GROW(leaks, leaknb + 1, leaksz);
+	return leaks[leaknb++] = ptr;
+}
+#endif
diff --git a/cache.h b/cache.h
index 101ead5..33603bb 100644
--- a/cache.h
+++ b/cache.h
@@ -777,6 +777,11 @@ int decode_85(char *dst, const char *line, int linelen);
 void encode_85(char *buf, const unsigned char *data, int bytes);
 
 /* alloc.c */
+#ifdef COLLECT_LEAKS_AT_EXIT
+extern void *leaky(void *);
+#else
+# define leaky(x) x
+#endif
 extern void *alloc_blob_node(void);
 extern void *alloc_tree_node(void);
 extern void *alloc_commit_node(void);
-- 
1.5.6.120.g3adb8.dirty