Module Name:    src
Committed By:   sjg
Date:           Thu Dec  9 22:30:17 UTC 2010

Modified Files:
        src/usr.bin/make: main.c meta.c nonints.h

Log Message:
meta_oodate(): we should track 'latestdir' on a per process basis.
Also, only consider target out of date if a not-found file is outside
'CWD'.  Ignore anything in "/tmp/" or tmpdir.


To generate a diff of this commit:
cvs rdiff -u -r1.190 -r1.191 src/usr.bin/make/main.c
cvs rdiff -u -r1.4 -r1.5 src/usr.bin/make/meta.c
cvs rdiff -u -r1.60 -r1.61 src/usr.bin/make/nonints.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/main.c
diff -u src/usr.bin/make/main.c:1.190 src/usr.bin/make/main.c:1.191
--- src/usr.bin/make/main.c:1.190	Mon Sep 13 15:36:57 2010
+++ src/usr.bin/make/main.c	Thu Dec  9 22:30:16 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.190 2010/09/13 15:36:57 sjg Exp $	*/
+/*	$NetBSD: main.c,v 1.191 2010/12/09 22:30:16 sjg Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -69,7 +69,7 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: main.c,v 1.190 2010/09/13 15:36:57 sjg Exp $";
+static char rcsid[] = "$NetBSD: main.c,v 1.191 2010/12/09 22:30:16 sjg Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
@@ -81,7 +81,7 @@
 #if 0
 static char sccsid[] = "@(#)main.c	8.3 (Berkeley) 3/19/94";
 #else
-__RCSID("$NetBSD: main.c,v 1.190 2010/09/13 15:36:57 sjg Exp $");
+__RCSID("$NetBSD: main.c,v 1.191 2010/12/09 22:30:16 sjg Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -1966,20 +1966,10 @@
     }
 }
 
-/*
- * Create and open a temp file using "pattern".
- * If "fnamep" is provided set it to a copy of the filename created.
- * Otherwise unlink the file once open.
- */
-int
-mkTempFile(const char *pattern, char **fnamep)
+char *
+getTmpdir(void)
 {
     static char *tmpdir = NULL;
-    char tfile[MAXPATHLEN];
-    int fd;
-    
-    if (!pattern)
-	pattern = TMPPAT;
 
     if (!tmpdir) {
 	struct stat st;
@@ -1994,6 +1984,25 @@
 	    tmpdir = bmake_strdup(_PATH_TMP);
 	}
     }
+    return tmpdir;
+}
+
+/*
+ * Create and open a temp file using "pattern".
+ * If "fnamep" is provided set it to a copy of the filename created.
+ * Otherwise unlink the file once open.
+ */
+int
+mkTempFile(const char *pattern, char **fnamep)
+{
+    static char *tmpdir = NULL;
+    char tfile[MAXPATHLEN];
+    int fd;
+    
+    if (!pattern)
+	pattern = TMPPAT;
+    if (!tmpdir)
+	tmpdir = getTmpdir();
     if (pattern[0] == '/') {
 	snprintf(tfile, sizeof(tfile), "%s", pattern);
     } else {

Index: src/usr.bin/make/meta.c
diff -u src/usr.bin/make/meta.c:1.4 src/usr.bin/make/meta.c:1.5
--- src/usr.bin/make/meta.c:1.4	Sat Nov 27 05:02:35 2010
+++ src/usr.bin/make/meta.c	Thu Dec  9 22:30:17 2010
@@ -695,15 +695,24 @@
 /*
  * When running with 'meta' functionality, a target can be out-of-date
  * if any of the references in it's meta data file is more recent.
+ * We have to track the latestdir on a per-process basis.
  */
+#define LDIR_VNAME_FMT ".meta.%d.ldir"
+
 Boolean
 meta_oodate(GNode *gn, Boolean oodate)
 {
+    static char *tmpdir = NULL;
+    char ldir_vname[64];
+    char cwd[MAXPATHLEN];
     char latestdir[MAXPATHLEN];
     char fname[MAXPATHLEN];
     char fname1[MAXPATHLEN];
+    char fname2[MAXPATHLEN];
     char *p;
     char *cp;
+    size_t cwdlen;
+    size_t tmplen = 0;
     FILE *fp;
     Boolean ignoreOODATE = FALSE;
 
@@ -718,7 +727,7 @@
      */
     Make_DoAllVar(gn);
 
-    if (getcwd(latestdir, sizeof(latestdir)) == NULL)
+    if (getcwd(cwd, sizeof(cwd)) == NULL)
 	err(1, "Could not get current working directory");
 
     meta_name(gn, fname, sizeof(fname), NULL, NULL);
@@ -727,6 +736,8 @@
 	static char *buf = NULL;
 	static size_t bufsz;
 	int lineno = 0;
+	int lastpid = 0;
+	int pid;
 	int f = 0;
 	int x;
 	LstNode ln;
@@ -736,10 +747,17 @@
 	    bufsz = 8 * BUFSIZ;
 	    buf = bmake_malloc(bufsz);
 	}
-	
+
+	if (!tmpdir) {
+	    tmpdir = getTmpdir();
+	    tmplen = strlen(tmpdir);
+	}
+
 	/* we want to track all the .meta we read */
 	Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL);
 
+	cwdlen = strlen(cwd);
+
 	ln = Lst_First(gn->commands);
 	while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) {
 	    lineno++;
@@ -764,28 +782,102 @@
 	    p = buf;
 	    strsep(&p, " ");
 	    if (f) {
+		/*
+		 * We are in the 'filemon' output section.
+		 * Each record from filemon follows the general form:
+		 *
+		 * <key> <pid> <data>
+		 *
+		 * Where:
+		 * <key> is a single letter, denoting the syscall.
+		 * <pid> is the process that made the syscall.
+		 * <data> is the arguments (of interest).
+		 */
+		switch(buf[0]) {
+		case '#':		/* comment */
+		case 'V':		/* version */
+		    break;
+		default:
+		    /*
+		     * We need to track pathnames per-process.
+		     *
+		     * Each process run by make, starts off in the 'CWD'
+		     * recorded in the .meta file, if it chdirs ('C')
+		     * elsewhere we need to track that - but only for
+		     * that process.  If it forks ('F'), we initialize
+		     * the child to have the same cwd as its parent.
+		     *
+		     * We also need to track the 'latestdir' of
+		     * interest.  This is usually the same as cwd, but
+		     * not if a process is reading directories.
+		     *
+		     * Each time we spot a different process ('pid')
+		     * we save the current value of 'latestdir' in a
+		     * variable qualified by 'lastpid', and
+		     * re-initialize 'latestdir' to any pre-saved
+		     * value for the current 'pid' and 'CWD' if none.
+		     */
+		    pid = atoi(p);
+		    if (pid > 0 && pid != lastpid) {
+			char *ldir;
+			char *tp;
+		    
+			if (lastpid > 0) {
+			    /* We need to remember this. */
+			    Var_Set(ldir_vname, latestdir, VAR_GLOBAL, 0);
+			}
+			snprintf(ldir_vname, sizeof(ldir_vname), LDIR_VNAME_FMT, pid);
+			lastpid = pid;
+			ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp);
+			if (ldir) {
+			    strlcpy(latestdir, ldir, sizeof(latestdir));
+			    if (tp)
+				free(tp);
+			} else 
+			    strlcpy(latestdir, cwd, sizeof(latestdir));
+		    }
+		    /* Skip past the pid. */
+		    if (strsep(&p, " ") == NULL)
+			continue;
+		    break;
+		}
+
 		/* Process according to record type. */
 		switch (buf[0]) {
-		case 'C':
-		    /* Skip the pid. */
-		    if (strsep(&p, " ") == NULL)
-			break;
+		case 'X':		/* eXit */
+		    Var_Delete(ldir_vname, VAR_GLOBAL);
+		    lastpid = 0;	/* no need to save ldir_vname */
+		    break;
 
+		case 'F':		/* [v]Fork */
+		    {
+			char cldir[64];
+			int child;
+
+			child = atoi(p);
+			if (child > 0) {
+			    snprintf(cldir, sizeof(cldir), LDIR_VNAME_FMT, child);
+			    Var_Set(cldir, latestdir, VAR_GLOBAL, 0);
+			}
+		    }
+		    break;
+
+		case 'C':		/* Chdir */
 		    /* Update the latest directory. */
 		    strlcpy(latestdir, p, sizeof(latestdir));
 		    break;
 
-		case 'R':
-		case 'E':
-		    /* Skip the pid. */
-		    if (strsep(&p, " ") == NULL)
-			break;
-
+		case 'R':		/* Read */
+		case 'E':		/* Exec */
 		    /*
 		     * Check for runtime files that can't
 		     * be part of the dependencies because
 		     * they are _expected_ to change.
 		     */
+		    if (strncmp(p, "/tmp/", 5) == 0 ||
+			strncmp(p, tmpdir, tmplen) == 0)
+			break;
+
 		    if (strncmp(p, "/var/", 5) == 0)
 			break;
 
@@ -798,39 +890,69 @@
 			break;
 
 		    /*
-		     * The rest of the record is the
-		     * file name.
-		     * Check if it's not an absolute
-		     * path.
+		     * The rest of the record is the file name.
+		     * Check if it's not an absolute path.
 		     */
-		    if (*p != '/') {
-			/* Use the latest path seen. */
-			snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p);
-			p = fname1;
-		    }
+		    {
+			char *sdirs[4];
+			char **sdp;
+			int sdx = 0;
+			int found = 0;
+
+			if (*p == '/') {
+			    sdirs[sdx++] = p; /* done */
+			} else {
+			    if (strcmp(".", p) == 0)
+				continue;  /* no point */
+
+			    /* Check vs latestdir */
+			    snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p);
+			    sdirs[sdx++] = fname1;
+
+			    if (strcmp(latestdir, cwd) != 0) {
+				/* Check vs cwd */
+				snprintf(fname2, sizeof(fname2), "%s/%s", cwd, p);
+				sdirs[sdx++] = fname2;
+			    }
+			}
+			sdirs[sdx++] = NULL;
 
-		    if (stat(p, &fs) == 0) {
-			if (!S_ISDIR(fs.st_mode) &&
-			    fs.st_mtime > gn->mtime) {
+			for (sdp = sdirs; *sdp && !found; sdp++) {
+			    if (stat(*sdp, &fs) == 0) {
+				found = 1;
+				p = *sdp;
+			    }
+			}
+			if (found) {
+			    if (!S_ISDIR(fs.st_mode) &&
+				fs.st_mtime > gn->mtime) {
+				if (DEBUG(META))
+				    fprintf(debug_file, "%s: %d: file '%s' is newer than the target...\n", fname, lineno, p);
+				oodate = TRUE;
+			    } else if (S_ISDIR(fs.st_mode)) {
+				/* Update the latest directory. */
+				realpath(p, latestdir);
+			    }
+			} else if (errno == ENOENT && *p == '/' &&
+				   strncmp(p, cwd, cwdlen) != 0) {
+			    /*
+			     * A referenced file outside of CWD is missing.
+			     * We cannot catch every eventuality here...
+			     */
 			    if (DEBUG(META))
-				fprintf(debug_file, "%s: %d: file '%s' is newer than the target...\n", fname, lineno, p);
+				fprintf(debug_file, "%s: %d: file '%s' may have moved?...\n", fname, lineno, p);
 			    oodate = TRUE;
 			}
-		    } else if (errno == ENOENT) {
-			if (DEBUG(META))
-			    fprintf(debug_file, "%s: %d: file '%s' may have moved?...\n", fname, lineno, p);
-			oodate = TRUE;
 		    }
 		    break;
 		default:
 		    break;
 		}
-
+	    } else if (strcmp(buf, "CMD") == 0) {
 		/*
 		 * Compare the current command with the one in the
 		 * meta data file.
 		 */
-	    } else if (strcmp(buf, "CMD") == 0) {
 		if (ln == NULL) {
 		    if (DEBUG(META))
 			fprintf(debug_file, "%s: %d: there were more build commands in the meta data file than there are now...\n", fname, lineno);

Index: src/usr.bin/make/nonints.h
diff -u src/usr.bin/make/nonints.h:1.60 src/usr.bin/make/nonints.h:1.61
--- src/usr.bin/make/nonints.h:1.60	Sat Aug  7 06:44:08 2010
+++ src/usr.bin/make/nonints.h	Thu Dec  9 22:30:17 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: nonints.h,v 1.60 2010/08/07 06:44:08 sjg Exp $	*/
+/*	$NetBSD: nonints.h,v 1.61 2010/12/09 22:30:17 sjg Exp $	*/
 
 /*-
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -124,6 +124,7 @@
 void Finish(int);
 int eunlink(const char *);
 void execError(const char *, const char *);
+char *getTmpdir(void);
 
 /* parse.c */
 void Parse_Error(int, const char *, ...)

Reply via email to