Workaround the race condition issue on updating cache
authorAkira TAGOH <akira@tagoh.org>
Wed, 2 Oct 2013 07:34:34 +0000 (16:34 +0900)
committerAkira TAGOH <akira@tagoh.org>
Wed, 2 Oct 2013 07:34:34 +0000 (16:34 +0900)
fc-cache/fc-cache.c
fontconfig/fontconfig.h
src/fcstr.c

index aeb0af2..af7ba6d 100644 (file)
@@ -118,7 +118,7 @@ usage (char *program, int error)
 static FcStrSet *processed_dirs;
 
 static int
-scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force, FcBool verbose, int *changed)
+scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force, FcBool verbose, FcBool recursive, int *changed)
 {
     int                    ret = 0;
     const FcChar8   *dir;
@@ -141,7 +141,7 @@ scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force,
            fflush (stdout);
        }
        
-       if (FcStrSetMember (processed_dirs, dir))
+       if (recursive && FcStrSetMember (processed_dirs, dir))
        {
            if (verbose)
                printf ("skipping, looped directory detected\n");
@@ -213,32 +213,37 @@ scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force,
                ret++;
            }
        }
-       
-       subdirs = FcStrSetCreate ();
-       if (!subdirs)
+
+       if (recursive)
        {
-           fprintf (stderr, "%s: Can't create subdir set\n", dir);
-           ret++;
-           FcDirCacheUnload (cache);
-           continue;
-       }
-       for (i = 0; i < FcCacheNumSubdir (cache); i++)
-           FcStrSetAdd (subdirs, FcCacheSubdir (cache, i));
+           subdirs = FcStrSetCreate ();
+           if (!subdirs)
+           {
+               fprintf (stderr, "%s: Can't create subdir set\n", dir);
+               ret++;
+               FcDirCacheUnload (cache);
+               continue;
+           }
+           for (i = 0; i < FcCacheNumSubdir (cache); i++)
+               FcStrSetAdd (subdirs, FcCacheSubdir (cache, i));
        
-       FcDirCacheUnload (cache);
+           FcDirCacheUnload (cache);
        
-       sublist = FcStrListCreate (subdirs);
-       FcStrSetDestroy (subdirs);
-       if (!sublist)
-       {
-           fprintf (stderr, "%s: Can't create subdir list\n", dir);
-           ret++;
-           continue;
+           sublist = FcStrListCreate (subdirs);
+           FcStrSetDestroy (subdirs);
+           if (!sublist)
+           {
+               fprintf (stderr, "%s: Can't create subdir list\n", dir);
+               ret++;
+               continue;
+           }
+           FcStrSetAdd (processed_dirs, dir);
+           ret += scanDirs (sublist, config, force, really_force, verbose, recursive, changed);
+           FcStrListDone (sublist);
        }
-       FcStrSetAdd (processed_dirs, dir);
-       ret += scanDirs (sublist, config, force, really_force, verbose, changed);
+       else
+           FcDirCacheUnload (cache);
     }
-    FcStrListDone (list);
     return ret;
 }
 
@@ -366,7 +371,11 @@ main (int argc, char **argv)
     }
        
     changed = 0;
-    ret = scanDirs (list, config, force, really_force, verbose, &changed);
+    ret = scanDirs (list, config, force, really_force, verbose, FcTrue, &changed);
+    /* Update the directory cache again to avoid the race condition as much as possible */
+    FcStrListFirst (list);
+    ret += scanDirs (list, config, FcTrue, really_force, verbose, FcFalse, &changed);
+    FcStrListDone (list);
 
     /*
      * Try to create CACHEDIR.TAG anyway.
@@ -379,6 +388,8 @@ main (int argc, char **argv)
 
     cleanCacheDirectories (config, verbose);
 
+    FcConfigDestroy (config);
+    FcFini ();
     /* 
      * Now we need to sleep a second  (or two, to be extra sure), to make
      * sure that timestamps for changes after this run of fc-cache are later
@@ -386,8 +397,7 @@ main (int argc, char **argv)
      * sleep(3) can't be interrupted by a signal here -- this isn't in the
      * library, and there aren't any signals flying around here.
      */
-    FcConfigDestroy (config);
-    FcFini ();
+    /* the resolution of mtime on FAT is 2 seconds */
     if (changed)
        sleep (2);
     if (verbose)
index 58912f5..e588579 100644 (file)
@@ -974,6 +974,9 @@ FcStrSetDestroy (FcStrSet *set);
 FcPublic FcStrList *
 FcStrListCreate (FcStrSet *set);
 
+FcPublic void
+FcStrListFirst (FcStrList *list);
+
 FcPublic FcChar8 *
 FcStrListNext (FcStrList *list);
 
index 3a32031..5707172 100644 (file)
@@ -1374,6 +1374,12 @@ FcStrListCreate (FcStrSet *set)
     return list;
 }
 
+void
+FcStrListFirst (FcStrList *list)
+{
+    list->n = 0;
+}
+
 FcChar8 *
 FcStrListNext (FcStrList *list)
 {