* [RFC] leaky()
@ 2008-06-24 20:14 Pierre Habouzit
2008-06-24 20:14 ` [PATCH 1/2] Introduce leaky() Pierre Habouzit
0 siblings, 1 reply; 9+ messages in thread
From: Pierre Habouzit @ 2008-06-24 20:14 UTC (permalink / raw)
To: git; +Cc: gitster
In the parse-options thread, it appears that we may somethings leak some
tiny bits of memory on purpose. So that it makes life of people
searching for real memory leaks easier.
The second patch marks the leaks I'm responsible for in git (and that
I'm aware of) as leaky().
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] Introduce leaky().
2008-06-24 20:14 [RFC] leaky() Pierre Habouzit
@ 2008-06-24 20:14 ` Pierre Habouzit
2008-06-24 20:14 ` [PATCH 2/2] git-rev-parse: use leaky() Pierre Habouzit
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Pierre Habouzit @ 2008-06-24 20:14 UTC (permalink / raw)
To: git; +Cc: gitster, Pierre Habouzit
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 <madcoder@debian.org>
---
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
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/2] git-rev-parse: use leaky().
2008-06-24 20:14 ` [PATCH 1/2] Introduce leaky() Pierre Habouzit
@ 2008-06-24 20:14 ` Pierre Habouzit
2008-06-24 20:16 ` [PATCH 1/2] Introduce leaky() Pierre Habouzit
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Pierre Habouzit @ 2008-06-24 20:14 UTC (permalink / raw)
To: git; +Cc: gitster, Pierre Habouzit
Mark the mallocs that cmd_parseopt never frees as leaky so that nobody
loses time trying to fix them.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
builtin-rev-parse.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index a7860ed..02defbb 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -319,12 +319,12 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
s = strchr(sb.buf, ' ');
if (!s || *sb.buf == ' ') {
o->type = OPTION_GROUP;
- o->help = xstrdup(skipspaces(sb.buf));
+ o->help = leaky(xstrdup(skipspaces(sb.buf)));
continue;
}
o->type = OPTION_CALLBACK;
- o->help = xstrdup(skipspaces(s));
+ o->help = leaky(xstrdup(skipspaces(s)));
o->value = &parsed;
o->flags = PARSE_OPT_NOARG;
o->callback = &parseopt_dump;
@@ -349,10 +349,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
if (s - sb.buf == 1) /* short option only */
o->short_name = *sb.buf;
else if (sb.buf[1] != ',') /* long option only */
- o->long_name = xmemdupz(sb.buf, s - sb.buf);
+ o->long_name = leaky(xmemdupz(sb.buf, s - sb.buf));
else {
o->short_name = *sb.buf;
- o->long_name = xmemdupz(sb.buf + 2, s - sb.buf - 2);
+ o->long_name = leaky(xmemdupz(sb.buf + 2, s - sb.buf - 2));
}
}
strbuf_release(&sb);
--
1.5.6.120.g3adb8.dirty
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] Introduce leaky().
2008-06-24 20:14 ` [PATCH 1/2] Introduce leaky() Pierre Habouzit
2008-06-24 20:14 ` [PATCH 2/2] git-rev-parse: use leaky() Pierre Habouzit
@ 2008-06-24 20:16 ` Pierre Habouzit
2008-06-24 21:28 ` Jakub Narebski
2008-06-26 18:46 ` Junio C Hamano
3 siblings, 0 replies; 9+ messages in thread
From: Pierre Habouzit @ 2008-06-24 20:16 UTC (permalink / raw)
To: git; +Cc: gitster
[-- Attachment #1: Type: text/plain, Size: 440 bytes --]
On Tue, Jun 24, 2008 at 08:14:33PM +0000, Pierre Habouzit wrote:
> +static void release_leaks(void)
> +{
> + while (leaknb-- > 0)
> + free(*leaks++);
crap I sent the wrong patch... this is supposed to be:
+ free(leaks[leaknb]);
> + free(leaks);
> +}
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] Introduce leaky().
2008-06-24 20:14 ` [PATCH 1/2] Introduce leaky() Pierre Habouzit
2008-06-24 20:14 ` [PATCH 2/2] git-rev-parse: use leaky() Pierre Habouzit
2008-06-24 20:16 ` [PATCH 1/2] Introduce leaky() Pierre Habouzit
@ 2008-06-24 21:28 ` Jakub Narebski
2008-06-24 22:10 ` Pierre Habouzit
2008-06-26 18:46 ` Junio C Hamano
3 siblings, 1 reply; 9+ messages in thread
From: Jakub Narebski @ 2008-06-24 21:28 UTC (permalink / raw)
To: Pierre Habouzit; +Cc: git, gitster
Pierre Habouzit <madcoder@debian.org> writes:
> diff --git a/Makefile b/Makefile
> +#
> +# Define COLLECT_LEAKS_AT_EXIT if you want memory marked as leaky() at exit.
I think s/at exit/to be freed &/;
> diff --git a/cache.h b/cache.h
Hmmm... cache?
> /* alloc.c */
> +#ifdef COLLECT_LEAKS_AT_EXIT
> +extern void *leaky(void *);
> +#else
> +# define leaky(x) x
> +#endif
Not
+# define leaky(x) (x)
to be careful?
--
Jakub Narebski
Poland
ShadeHawk on #git
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] Introduce leaky().
2008-06-24 21:28 ` Jakub Narebski
@ 2008-06-24 22:10 ` Pierre Habouzit
0 siblings, 0 replies; 9+ messages in thread
From: Pierre Habouzit @ 2008-06-24 22:10 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git, gitster
[-- Attachment #1: Type: text/plain, Size: 874 bytes --]
On Tue, Jun 24, 2008 at 09:28:30PM +0000, Jakub Narebski wrote:
> Pierre Habouzit <madcoder@debian.org> writes:
>
> > diff --git a/Makefile b/Makefile
>
> > +#
> > +# Define COLLECT_LEAKS_AT_EXIT if you want memory marked as leaky() at exit.
>
> I think s/at exit/to be freed &/;
err obviously.
> > diff --git a/cache.h b/cache.h
>
> Hmmm... cache?
well cache.h has the prototypes for alloc.c that feels like the proper
place, but I don't care much :)
> > /* alloc.c */
> > +#ifdef COLLECT_LEAKS_AT_EXIT
> > +extern void *leaky(void *);
> > +#else
> > +# define leaky(x) x
> > +#endif
>
> Not
>
> +# define leaky(x) (x)
>
> to be careful?
ack.
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] Introduce leaky().
2008-06-24 20:14 ` [PATCH 1/2] Introduce leaky() Pierre Habouzit
` (2 preceding siblings ...)
2008-06-24 21:28 ` Jakub Narebski
@ 2008-06-26 18:46 ` Junio C Hamano
2008-06-26 21:33 ` Pierre Habouzit
3 siblings, 1 reply; 9+ messages in thread
From: Junio C Hamano @ 2008-06-26 18:46 UTC (permalink / raw)
To: Pierre Habouzit; +Cc: git
I looked at the patch (and your updated parseopt series that depends on
this that is queued at madism.org) again, but I have to say I do not like
it, not because I do not want leaks, nor because I do not want explicit
markings. The issue of helping valgrind sessions is worth addressing.
However.
First of all, it is unclear what the semantics of leaky() is. Do you want
to mark all things that will be unreacheable from anywhere in the program
at the end, or do you want to mark all things that we have obtained from
malloc(3) and friends but have not free(3)ed? Without a clear semantics
to use as the guiding principle, it would be hard for people to use this
macro properly to help debugging leaks.
Specifically, how would you envision to handle allocations of objects that
will be reachable from object.c::obj_hash at the program end? We do not
have to (and we should not) mark them using the former semantics, but we
should with the latter semantics.
The user would also need to worry about not freeing the original
allocation pointer when something is realloc(3)ed, which means either
finding the last realloc(3) of the object (that is logically the same, but
just being extended) and mark the pointer as leaky() after that realloc,
or unregister the original pointer from leaks before calling realloc and
register what comes back. It will easily get messy.
By the way, the series queued in your repository still has "s/pring/print/"
typo in 4/7 and "argv not NULL terminated" comment in 6/7.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] Introduce leaky().
2008-06-26 18:46 ` Junio C Hamano
@ 2008-06-26 21:33 ` Pierre Habouzit
2008-07-22 18:09 ` Jan Hudec
0 siblings, 1 reply; 9+ messages in thread
From: Pierre Habouzit @ 2008-06-26 21:33 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
[-- Attachment #1: Type: text/plain, Size: 1044 bytes --]
On Thu, Jun 26, 2008 at 06:46:43PM +0000, Junio C Hamano wrote:
> The user would also need to worry about not freeing the original
> allocation pointer when something is realloc(3)ed, which means either
> finding the last realloc(3) of the object (that is logically the same, but
> just being extended) and mark the pointer as leaky() after that realloc,
> or unregister the original pointer from leaks before calling realloc and
> register what comes back. It will easily get messy.
Hmm indeed, maybe it isn't such a good idea then.
> By the way, the series queued in your repository still has "s/pring/print/"
> typo in 4/7 and "argv not NULL terminated" comment in 6/7.
I'll fix that and pushed again, without the leaky() series dependency
(I've put in a comment that I'm aware that it's a leak), and with the
two fixes you mention done.
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] Introduce leaky().
2008-06-26 21:33 ` Pierre Habouzit
@ 2008-07-22 18:09 ` Jan Hudec
0 siblings, 0 replies; 9+ messages in thread
From: Jan Hudec @ 2008-07-22 18:09 UTC (permalink / raw)
To: Pierre Habouzit, Junio C Hamano, git
On Thu, Jun 26, 2008 at 23:33:04 +0200, Pierre Habouzit wrote:
> On Thu, Jun 26, 2008 at 06:46:43PM +0000, Junio C Hamano wrote:
> > The user would also need to worry about not freeing the original
> > allocation pointer when something is realloc(3)ed, which means either
> > finding the last realloc(3) of the object (that is logically the same, but
> > just being extended) and mark the pointer as leaky() after that realloc,
> > or unregister the original pointer from leaks before calling realloc and
> > register what comes back. It will easily get messy.
>
> Hmm indeed, maybe it isn't such a good idea then.
I don't think it's necessary either. Valgrind (unlike other leak detectors
the poor windows folks are stuck with) is quite smart and will only report
memory as leaked when there is no pointer to it. So it should not report any
memory pointed to by index or any other static structure.
Additionally since valgrind allows one to write rules to exclude
uninteresting reports. So a good approach would be to just keep such
exclusion file around in git with the known uninteresting cases.
> > By the way, the series queued in your repository still has "s/pring/print/"
> > typo in 4/7 and "argv not NULL terminated" comment in 6/7.
>
> I'll fix that and pushed again, without the leaky() series dependency
> (I've put in a comment that I'm aware that it's a leak), and with the
> two fixes you mention done.
>
> --
> ·O· Pierre Habouzit
> ··O madcoder@debian.org
> OOO http://www.madism.org
--
Jan 'Bulb' Hudec <bulb@ucw.cz>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2008-07-22 18:10 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-24 20:14 [RFC] leaky() Pierre Habouzit
2008-06-24 20:14 ` [PATCH 1/2] Introduce leaky() Pierre Habouzit
2008-06-24 20:14 ` [PATCH 2/2] git-rev-parse: use leaky() Pierre Habouzit
2008-06-24 20:16 ` [PATCH 1/2] Introduce leaky() Pierre Habouzit
2008-06-24 21:28 ` Jakub Narebski
2008-06-24 22:10 ` Pierre Habouzit
2008-06-26 18:46 ` Junio C Hamano
2008-06-26 21:33 ` Pierre Habouzit
2008-07-22 18:09 ` Jan Hudec
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).