Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/make make: fix memory leak for filenames in .for loo...



details:   https://anonhg.NetBSD.org/src/rev/dabe985ab2e8
branches:  trunk
changeset: 1027619:dabe985ab2e8
user:      rillig <rillig%NetBSD.org@localhost>
date:      Mon Dec 13 05:25:04 2021 +0000

description:
make: fix memory leak for filenames in .for loops (since 2013-06-18)

Previously, each time a .for directive pushed its buffer on the input
file stack, the current filename was duplicated.  This was a waste of
memory.

The name of a file is typically only used while it is read in.  There is
one situation when the filename is needed for longer, which is when a
target is defined.

Since .for loops are implemented as a special form of included files,
each .for loop duplicated the current filename as well.

$ cat << EOF > for.mk
.for i in 1 2 3 4 5 6 7 8 9 0
.for i in 1 2 3 4 5 6 7 8 9 0
.for i in 1 2 3 4 5 6 7 8 9 0
.for i in 1 2 3 4 5 6 7 8 9 0
.for i in 1 2 3 4 5 6 7 8 9 0
.for i in 1 2 3 4 5 6 7 8 9 0
.for i in 1 2 3 4 5 6 7 8 9 0
.endfor
.endfor
.endfor
.endfor
.endfor
.endfor
.endfor

all:
        @ps -o rsz -p ${.MAKE.PID}
EOF

$ make-2021.12.13.03.55.16 -r -f for.mk
  RSZ
10720

$ ./make -r -f for.mk
 RSZ
1716

The difference is 8 MB, which amounts to 1 million .for loops.

diffstat:

 usr.bin/make/main.c  |   5 +++--
 usr.bin/make/make.h  |   5 ++---
 usr.bin/make/parse.c |  32 +++++++++++++++-----------------
 usr.bin/make/str.c   |  21 +++++++++++++++++++--
 usr.bin/make/str.h   |   5 ++++-
 5 files changed, 43 insertions(+), 25 deletions(-)

diffs (223 lines):

diff -r 591604dd12c7 -r dabe985ab2e8 usr.bin/make/main.c
--- a/usr.bin/make/main.c       Mon Dec 13 04:18:01 2021 +0000
+++ b/usr.bin/make/main.c       Mon Dec 13 05:25:04 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: main.c,v 1.541 2021/08/14 13:32:12 rillig Exp $        */
+/*     $NetBSD: main.c,v 1.542 2021/12/13 05:25:04 rillig Exp $        */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -111,7 +111,7 @@
 #include "trace.h"
 
 /*     "@(#)main.c     8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: main.c,v 1.541 2021/08/14 13:32:12 rillig Exp $");
+MAKE_RCSID("$NetBSD: main.c,v 1.542 2021/12/13 05:25:04 rillig Exp $");
 #if defined(MAKE_NATIVE) && !defined(lint)
 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
            "The Regents of the University of California.  "
@@ -1346,6 +1346,7 @@
        /* default to writing debug to stderr */
        opts.debug_file = stderr;
 
+       Str_Intern_Init();
        HashTable_Init(&cached_realpaths);
 
 #ifdef SIGINFO
diff -r 591604dd12c7 -r dabe985ab2e8 usr.bin/make/make.h
--- a/usr.bin/make/make.h       Mon Dec 13 04:18:01 2021 +0000
+++ b/usr.bin/make/make.h       Mon Dec 13 05:25:04 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: make.h,v 1.270 2021/11/28 23:12:51 rillig Exp $        */
+/*     $NetBSD: make.h,v 1.271 2021/12/13 05:25:04 rillig Exp $        */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -435,8 +435,7 @@
         * everyone but the Suff module) */
        struct Suffix *suffix;
 
-       /* Filename where the GNode got defined */
-       /* XXX: What is the lifetime of this string? */
+       /* Filename where the GNode got defined, unlimited lifetime */
        const char *fname;
        /* Line number where the GNode got defined */
        int lineno;
diff -r 591604dd12c7 -r dabe985ab2e8 usr.bin/make/parse.c
--- a/usr.bin/make/parse.c      Mon Dec 13 04:18:01 2021 +0000
+++ b/usr.bin/make/parse.c      Mon Dec 13 05:25:04 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: parse.c,v 1.575 2021/12/13 00:09:07 rillig Exp $       */
+/*     $NetBSD: parse.c,v 1.576 2021/12/13 05:25:04 rillig Exp $       */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -109,7 +109,7 @@
 #include "pathnames.h"
 
 /*     "@(#)parse.c    8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: parse.c,v 1.575 2021/12/13 00:09:07 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.576 2021/12/13 05:25:04 rillig Exp $");
 
 /* types and constants */
 
@@ -117,7 +117,7 @@
  * Structure for a file being read ("included file")
  */
 typedef struct IFile {
-       char *fname;            /* name of file (relative? absolute?) */
+       FStr name;              /* absolute or relative to the cwd */
        bool fromForLoop;       /* simulated .include by the .for loop */
        int lineno;             /* current line number in file */
        int first_lineno;       /* line number of start of text */
@@ -491,7 +491,7 @@
 
        for (i = n; i-- > 0;) {
                const IFile *entry = entries + i;
-               const char *fname = entry->fname;
+               const char *fname = entry->name.str;
                bool printLineno;
                char dirbuf[MAXPATHLEN + 1];
 
@@ -533,7 +533,7 @@
 RememberLocation(GNode *gn)
 {
        IFile *curFile = CurFile();
-       gn->fname = curFile->fname;
+       gn->fname = Str_Intern(curFile->name.str);
        gn->lineno = curFile->lineno;
 }
 
@@ -662,7 +662,7 @@
                lineno = 0;
        } else {
                IFile *curFile = CurFile();
-               fname = curFile->fname;
+               fname = curFile->name.str;
                lineno = (size_t)curFile->lineno;
        }
 
@@ -2143,7 +2143,7 @@
                 * we can locate the file.
                 */
 
-               incdir = bmake_strdup(CurFile()->fname);
+               incdir = bmake_strdup(CurFile()->name.str);
                slash = strrchr(incdir, '/');
                if (slash != NULL) {
                        *slash = '\0';
@@ -2322,7 +2322,7 @@
 
        for (i = includes.len; i >= 2; i--)
                if (!incs[i - 1].fromForLoop)
-                       return incs[i - 2].fname;
+                       return incs[i - 2].name.str;
        return NULL;
 }
 
@@ -2413,7 +2413,7 @@
        bool fromForLoop = name == NULL;
 
        if (fromForLoop)
-               name = CurFile()->fname;
+               name = CurFile()->name.str;
        else
                ParseTrackInput(name);
 
@@ -2426,7 +2426,7 @@
                return;
 
        curFile = Vector_Push(&includes);
-       curFile->fname = bmake_strdup(name);
+       curFile->name = FStr_InitOwn(bmake_strdup(name));
        curFile->fromForLoop = fromForLoop;
        curFile->lineno = lineno;
        curFile->first_lineno = lineno;
@@ -2441,8 +2441,7 @@
        buf = curFile->readMore(curFile->readMoreArg, &len);
        if (buf == NULL) {
                /* Was all a waste of time ... */
-               if (curFile->fname != NULL)
-                       free(curFile->fname);
+               FStr_Done(&curFile->name);
                free(curFile);
                return;
        }
@@ -2605,8 +2604,7 @@
                curFile->lf = NULL;
        }
 
-       /* Dispose of curFile info */
-       /* Leak curFile->fname because all the GNodes have pointers to it. */
+       FStr_Done(&curFile->name);
        free(curFile->buf_freeIt);
        Vector_Pop(&includes);
 
@@ -2621,9 +2619,9 @@
 
        curFile = CurFile();
        DEBUG2(PARSE, "ParseEOF: returning to file %s, line %d\n",
-           curFile->fname, curFile->lineno);
-
-       ParseSetParseFile(curFile->fname);
+           curFile->name.str, curFile->lineno);
+
+       ParseSetParseFile(curFile->name.str);
        return true;
 }
 
diff -r 591604dd12c7 -r dabe985ab2e8 usr.bin/make/str.c
--- a/usr.bin/make/str.c        Mon Dec 13 04:18:01 2021 +0000
+++ b/usr.bin/make/str.c        Mon Dec 13 05:25:04 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: str.c,v 1.86 2021/06/21 16:59:18 rillig Exp $  */
+/*     $NetBSD: str.c,v 1.87 2021/12/13 05:25:04 rillig Exp $  */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -71,7 +71,11 @@
 #include "make.h"
 
 /*     "@(#)str.c      5.8 (Berkeley) 6/1/90"  */
-MAKE_RCSID("$NetBSD: str.c,v 1.86 2021/06/21 16:59:18 rillig Exp $");
+MAKE_RCSID("$NetBSD: str.c,v 1.87 2021/12/13 05:25:04 rillig Exp $");
+
+
+static HashTable interned_strings;
+
 
 /* Return the concatenation of s1 and s2, freshly allocated. */
 char *
@@ -395,3 +399,16 @@
                str++;
        }
 }
+
+void
+Str_Intern_Init(void)
+{
+       HashTable_Init(&interned_strings);
+}
+
+/* Return a canonical instance of str, with unlimited lifetime. */
+const char *
+Str_Intern(const char *str)
+{
+       return HashTable_CreateEntry(&interned_strings, str, NULL)->key;
+}
diff -r 591604dd12c7 -r dabe985ab2e8 usr.bin/make/str.h
--- a/usr.bin/make/str.h        Mon Dec 13 04:18:01 2021 +0000
+++ b/usr.bin/make/str.h        Mon Dec 13 05:25:04 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: str.h,v 1.13 2021/12/12 23:39:34 rillig Exp $  */
+/*     $NetBSD: str.h,v 1.14 2021/12/13 05:25:04 rillig Exp $  */
 
 /*
  Copyright (c) 2021 Roland Illig <rillig%NetBSD.org@localhost>
@@ -343,3 +343,6 @@
 char *str_concat3(const char *, const char *, const char *);
 
 bool Str_Match(const char *, const char *);
+
+void Str_Intern_Init(void);
+const char *Str_Intern(const char *);



Home | Main Index | Thread Index | Old Index