- Work around a bug in glibc glob(3), by avoiding GLOB_NOCHECK.
authorPaul Smith <psmith@gnu.org>
Sat, 6 Jun 2009 23:16:46 +0000 (23:16 +0000)
committerPaul Smith <psmith@gnu.org>
Sat, 6 Jun 2009 23:16:46 +0000 (23:16 +0000)
- Fix issue in very parallel builds found building glibc.

ChangeLog
read.c
remake.c
tests/scripts/variables/SHELL

index a3ea3e4..1c2d0c4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2009-06-06  Paul Smith  <psmith@gnu.org>
+
+       * remake.c (check_dep): Only set the target's state to not-started
+       if it's not already running.  Found this while testing -j10 builds
+       of glibc: various targets were being rebuilt multiple times.
+
+       * read.c (multi_glob): Don't pass GLOB_NOCHECK to glob(3); instead
+       handle the GLOB_NOMATCH error.  This is to work around Sourceware.org
+       Bugzilla bug 10246.
+
 2009-06-04  Paul Smith  <psmith@gnu.org>
 
        * read.c (eval): Skip initial whitespace (ffeed, vtab, etc.)
diff --git a/read.c b/read.c
index aa13a21..0459f8c 100644 (file)
--- a/read.c
+++ b/read.c
@@ -3083,6 +3083,9 @@ multi_glob (struct nameseq *chain, unsigned int size)
 
   for (old = chain; old != 0; old = nexto)
     {
+      int r;
+      const char **nlist = 0;
+      int i = 0;
       const char *gname;
 #ifndef NO_ARCHIVES
       char *arname = 0;
@@ -3109,76 +3112,78 @@ multi_glob (struct nameseq *chain, unsigned int size)
        }
 #endif /* !NO_ARCHIVES */
 
-      switch (glob (gname, GLOB_NOCHECK|GLOB_ALTDIRFUNC, NULL, &gl))
+      r = glob (gname, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl);
+      switch (r)
        {
-       case 0:                 /* Success.  */
-         {
-           int i = gl.gl_pathc;
-           while (i-- > 0)
-             {
-#ifndef NO_ARCHIVES
-               if (memname != 0)
-                 {
-                   /* Try to glob on MEMNAME within the archive.  */
-                   struct nameseq *found
-                     = ar_glob (gl.gl_pathv[i], memname, size);
-                   if (! found)
-                     {
-                       /* No matches.  Use MEMNAME as-is.  */
-                       unsigned int alen = strlen (gl.gl_pathv[i]);
-                       unsigned int mlen = strlen (memname);
-                        char *name;
-                       struct nameseq *elt = xmalloc (size);
-                        memset (elt, '\0', size);
-
-                        name = alloca (alen + 1 + mlen + 2);
-                       memcpy (name, gl.gl_pathv[i], alen);
-                       name[alen] = '(';
-                       memcpy (name+alen+1, memname, mlen);
-                       name[alen + 1 + mlen] = ')';
-                       name[alen + 1 + mlen + 1] = '\0';
-                        elt->name = strcache_add (name);
-                       elt->next = new;
-                       new = elt;
-                     }
-                   else
-                     {
-                       /* Find the end of the FOUND chain.  */
-                       struct nameseq *f = found;
-                       while (f->next != 0)
-                         f = f->next;
-
-                       /* Attach the chain being built to the end of the FOUND
-                          chain, and make FOUND the new NEW chain.  */
-                       f->next = new;
-                       new = found;
-                     }
-                 }
-               else
-#endif /* !NO_ARCHIVES */
-                 {
-                   struct nameseq *elt = xmalloc (size);
-                    memset (elt, '\0', size);
-                   elt->name = strcache_add (gl.gl_pathv[i]);
-                   elt->next = new;
-                   new = elt;
-                 }
-             }
-           globfree (&gl);
-           free (old);
-           break;
-         }
-
        case GLOB_NOSPACE:
          fatal (NILF, _("virtual memory exhausted"));
-         break;
+
+       case 0:
+          /* Success.  */
+          i = gl.gl_pathc;
+          nlist = (const char **)gl.gl_pathv;
+          break;
 
        default:
-         old->next = new;
-         new = old;
+          /* Not a match or another error; keep this name.  */
+          i = 1;
+          nlist = &gname;
          break;
        }
 
+      /* For each matched element, add it to the list.  */
+      while (i-- > 0)
+#ifndef NO_ARCHIVES
+        if (memname != 0)
+          {
+            /* Try to glob on MEMNAME within the archive.  */
+            struct nameseq *found
+              = ar_glob (nlist[i], memname, size);
+            if (! found)
+              {
+                /* No matches.  Use MEMNAME as-is.  */
+                unsigned int alen = strlen (nlist[i]);
+                unsigned int mlen = strlen (memname);
+                char *name;
+                struct nameseq *elt = xmalloc (size);
+                memset (elt, '\0', size);
+
+                name = alloca (alen + 1 + mlen + 2);
+                memcpy (name, nlist[i], alen);
+                name[alen] = '(';
+                memcpy (name+alen+1, memname, mlen);
+                name[alen + 1 + mlen] = ')';
+                name[alen + 1 + mlen + 1] = '\0';
+                elt->name = strcache_add (name);
+                elt->next = new;
+                new = elt;
+              }
+            else
+              {
+                /* Find the end of the FOUND chain.  */
+                struct nameseq *f = found;
+                while (f->next != 0)
+                  f = f->next;
+
+                /* Attach the chain being built to the end of the FOUND
+                   chain, and make FOUND the new NEW chain.  */
+                f->next = new;
+                new = found;
+              }
+          }
+        else
+#endif /* !NO_ARCHIVES */
+          {
+            struct nameseq *elt = xmalloc (size);
+            memset (elt, '\0', size);
+            elt->name = strcache_add (nlist[i]);
+            elt->next = new;
+            new = elt;
+          }
+
+      if (r == 0)
+        globfree (&gl);
+      free (old);
 #ifndef NO_ARCHIVES
       if (arname)
         free (arname);
index 2dad3f0..ab8dd80 100644 (file)
--- a/remake.c
+++ b/remake.c
@@ -984,10 +984,11 @@ check_dep (struct file *file, unsigned int depth,
          struct dep *lastd;
           int deps_running = 0;
 
-          /* Reset this target's state so that we check it fresh.  It could be
-             that it's already been checked as part of an order-only
+          /* If this target is not running, set it's state so that we check it
+             fresh.  It could be it was checked as part of an order-only
              prerequisite and so wasn't rebuilt then, but should be now.  */
-          set_command_state (file, cs_not_started);
+          if (file->command_state != cs_running)
+            set_command_state (file, cs_not_started);
 
          lastd = 0;
          d = file->deps;
index acc5903..a303540 100644 (file)
@@ -49,8 +49,11 @@ all:;@echo "$(SHELL) $$SHELL"
 
 $extraENV{SHELL} = $mshell;
 
-run_make_test("all: export SHELL := /./$mshell\n".'
-all:;@echo "$(SHELL) $$SHELL"
-', '', "/./$mshell /./$mshell");
+run_make_test("
+SHELL := /././$mshell
+one: two
+two: export SHELL := /./$mshell\n".'
+one two:;@echo "$@: $(SHELL) $$SHELL"
+', '', "two: /./$mshell /./$mshell\none: /././$mshell $mshell\n");
 
 1;