Blob Blame History Raw
From 0203055520206028eecee5d261887cdc91500e15 Mon Sep 17 00:00:00 2001
From: Akira TAGOH <akira@tagoh.org>
Date: Wed, 2 Oct 2013 16:34:34 +0900
Subject: [PATCH] Workaround the race condition issue on updating cache

---
 fc-cache/fc-cache.c     | 62 ++++++++++++++++++++++++++++---------------------
 fontconfig/fontconfig.h |  3 +++
 src/fcstr.c             |  6 +++++
 3 files changed, 45 insertions(+), 26 deletions(-)

diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index aeb0af2..af7ba6d 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -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 (1);
     if (verbose)
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index 58912f5..e588579 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -974,6 +974,9 @@ FcStrSetDestroy (FcStrSet *set);
 FcPublic FcStrList *
 FcStrListCreate (FcStrSet *set);
 
+FcPublic void
+FcStrListFirst (FcStrList *list);
+
 FcPublic FcChar8 *
 FcStrListNext (FcStrList *list);
 
diff --git a/src/fcstr.c b/src/fcstr.c
index 3a32031..5707172 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -1374,6 +1374,12 @@ FcStrListCreate (FcStrSet *set)
     return list;
 }
 
+void
+FcStrListFirst (FcStrList *list)
+{
+    list->n = 0;
+}
+
 FcChar8 *
 FcStrListNext (FcStrList *list)
 {
-- 
1.8.3.1

From 9a4310176bb11e1e826d238eb0761b7895b48883 Mon Sep 17 00:00:00 2001
From: Akira TAGOH <akira@tagoh.org>
Date: Wed, 9 Oct 2013 12:19:35 +0900
Subject: [PATCH] Add missing doc for FcStrListFirst and fix a typo

---
 doc/fcstrset.fncs | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/doc/fcstrset.fncs b/doc/fcstrset.fncs
index 737347b..b96489a 100644
--- a/doc/fcstrset.fncs
+++ b/doc/fcstrset.fncs
@@ -98,12 +98,20 @@ Destroys <parameter>set</parameter>.
 Creates an iterator to list the strings in <parameter>set</parameter>.
 @@
 
+@RET@		void
+@FUNC@		FcStrListFirst
+@TYPE1@		FcStrList *			@ARG1@		list
+@PURPOSE@	get first string in iteration
+@DESC@
+Returns the first string in <parameter>list</parameter>.
+@@
+
 @RET@		FcChar8 *
 @FUNC@		FcStrListNext
 @TYPE1@		FcStrList *			@ARG1@		list	
 @PURPOSE@	get next string in iteration
 @DESC@
-Returns the next string in <parameter>set</parameter>.
+Returns the next string in <parameter>list</parameter>.
 @@
 
 @RET@		void
-- 
1.8.3.1