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(1): fix the reference count of dotLast goi...



details:   https://anonhg.NetBSD.org/src/rev/6713c9689f7c
branches:  trunk
changeset: 978707:6713c9689f7c
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sun Nov 29 16:37:10 2020 +0000

description:
make(1): fix the reference count of dotLast going negative

The memory management for dotLast is quite simple.  It is initialized
exactly once main_Init > Init_Objdir > Dir_InitDir and freed exactly
once in main_CleanUp > Dir_End.  Previously, dotLast was not freed at all.

The first call to CachedDir_Unref decremented the refCount to 0 but
didn't free anything.  Next, CachedDir_Destroy was called, which
decremented the reference count to -1, therefore skipping the actual
freeing.  This was probably an implementation mistake.

Since Dir_End is called at the very end of main_CleanUp, no code
accesses dotLast after it has been freed.

diffstat:

 usr.bin/make/dir.c |  27 ++++++++++++++++++++-------
 1 files changed, 20 insertions(+), 7 deletions(-)

diffs (69 lines):

diff -r c38ed5b72b97 -r 6713c9689f7c usr.bin/make/dir.c
--- a/usr.bin/make/dir.c        Sun Nov 29 16:04:34 2020 +0000
+++ b/usr.bin/make/dir.c        Sun Nov 29 16:37:10 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dir.c,v 1.239 2020/11/29 16:04:34 rillig Exp $ */
+/*     $NetBSD: dir.c,v 1.240 2020/11/29 16:37:10 rillig Exp $ */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -136,7 +136,7 @@
 #include "job.h"
 
 /*     "@(#)dir.c      8.2 (Berkeley) 1/2/94"  */
-MAKE_RCSID("$NetBSD: dir.c,v 1.239 2020/11/29 16:04:34 rillig Exp $");
+MAKE_RCSID("$NetBSD: dir.c,v 1.240 2020/11/29 16:37:10 rillig Exp $");
 
 #define DIR_DEBUG0(text) DEBUG0(DIR, text)
 #define DIR_DEBUG1(fmt, arg1) DEBUG1(DIR, fmt, arg1)
@@ -271,8 +271,8 @@
 
 static CachedDir *dot;         /* contents of current directory */
 static CachedDir *cur;         /* contents of current directory, if not dot */
-static CachedDir *dotLast;     /* a fake path entry indicating we need to
-                                * look for . last */
+/* A fake path entry indicating we need to look for '.' last. */
+static CachedDir *dotLast = NULL;
 
 /* Results of doing a last-resort stat in Dir_FindFile -- if we have to go to
  * the system to find the file, we might as well have its mtime on record.
@@ -341,6 +341,20 @@
                CachedDir_Free0(dir);
 }
 
+/* Update the value of the CachedDir variable, updating the reference counts. */
+static void
+CachedDir_Assign(CachedDir **var, CachedDir *dir)
+{
+       CachedDir *prev;
+
+       prev = *var;
+       *var = dir;
+       if (dir != NULL)
+               CachedDir_Ref(dir);
+       if (prev != NULL)
+               CachedDir_Destroy(prev);
+}
+
 static void
 OpenDirs_Init(OpenDirs *odirs)
 {
@@ -466,7 +480,7 @@
 {
        Dir_InitCur(cdname);
 
-       dotLast = CachedDir_Ref(CachedDir_New(".DOTLAST"));
+       CachedDir_Assign(&dotLast, CachedDir_New(".DOTLAST"));
 }
 
 /*
@@ -537,8 +551,7 @@
                CachedDir_Unref(cur);   /* XXX: why unref twice? */
                CachedDir_Destroy(cur);
        }
-       CachedDir_Unref(dotLast);       /* XXX: why unref twice? */
-       CachedDir_Destroy(dotLast);
+       CachedDir_Assign(&dotLast, NULL);
        CachedDir_Unref(dot);           /* XXX: why unref twice? */
        CachedDir_Destroy(dot);
        SearchPath_Clear(&dirSearchPath);



Home | Main Index | Thread Index | Old Index