[fontconfig/f20] Fix the race condition issue on updating caches. (#921706)

Akira TAGOH tagoh at fedoraproject.org
Tue Jul 8 03:42:25 UTC 2014


commit a700bbddfb9c1ee91052b29a4b43574098cb41f6
Author: Akira TAGOH <tagoh at redhat.com>
Date:   Tue Jul 8 12:42:34 2014 +0900

    Fix the race condition issue on updating caches. (#921706)

 fontconfig-fix-race-condition.patch |  386 +++++++++++++++++++++++++++++++++++
 fontconfig.spec                     |    7 +-
 2 files changed, 392 insertions(+), 1 deletions(-)
---
diff --git a/fontconfig-fix-race-condition.patch b/fontconfig-fix-race-condition.patch
new file mode 100644
index 0000000..1cfbe90
--- /dev/null
+++ b/fontconfig-fix-race-condition.patch
@@ -0,0 +1,386 @@
+diff -pruN fontconfig-2.11.0.orig/fc-cache/fc-cache.c fontconfig-2.11.0/fc-cache/fc-cache.c
+--- fontconfig-2.11.0.orig/fc-cache/fc-cache.c	2013-10-11 12:10:17.000000000 +0900
++++ fontconfig-2.11.0/fc-cache/fc-cache.c	2014-07-08 12:37:59.000000000 +0900
+@@ -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, FcBool recursive, int *changed)
++scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force, FcBool verbose, FcBool recursive, int *changed, FcStrSet *updateDirs)
+ {
+     int		    ret = 0;
+     const FcChar8   *dir;
+@@ -137,7 +137,10 @@ scanDirs (FcStrList *list, FcConfig *con
+     {
+ 	if (verbose)
+ 	{
+-	    printf ("%s: ", dir);
++	    if (!recursive)
++		printf ("Re-scanning %s: ", dir);
++	    else
++		printf ("%s: ", dir);
+ 	    fflush (stdout);
+ 	}
+ 	
+@@ -184,8 +187,13 @@ scanDirs (FcStrList *list, FcConfig *con
+ 	
+ 	if (!cache)
+ 	{
+-	    (*changed)++;
+-	    cache = FcDirCacheRead (dir, FcTrue, config);
++	    if (!recursive)
++		cache = FcDirCacheRescan (dir, config);
++	    else
++	    {
++		(*changed)++;
++		cache = FcDirCacheRead (dir, FcTrue, config);
++	    }
+ 	    if (!cache)
+ 	    {
+ 		fprintf (stderr, "%s: error scanning\n", dir);
+@@ -226,6 +234,8 @@ scanDirs (FcStrList *list, FcConfig *con
+ 	    }
+ 	    for (i = 0; i < FcCacheNumSubdir (cache); i++)
+ 		FcStrSetAdd (subdirs, FcCacheSubdir (cache, i));
++	    if (updateDirs && FcCacheNumSubdir (cache) > 0)
++		FcStrSetAdd (updateDirs, dir);
+ 	
+ 	    FcDirCacheUnload (cache);
+ 	
+@@ -238,7 +248,7 @@ scanDirs (FcStrList *list, FcConfig *con
+ 		continue;
+ 	    }
+ 	    FcStrSetAdd (processed_dirs, dir);
+-	    ret += scanDirs (sublist, config, force, really_force, verbose, recursive, changed);
++	    ret += scanDirs (sublist, config, force, really_force, verbose, recursive, changed, updateDirs);
+ 	    FcStrListDone (sublist);
+ 	}
+ 	else
+@@ -271,7 +281,7 @@ cleanCacheDirectories (FcConfig *config,
+ int
+ main (int argc, char **argv)
+ {
+-    FcStrSet	*dirs;
++    FcStrSet	*dirs, *updateDirs;
+     FcStrList	*list;
+     FcBool    	verbose = FcFalse;
+     FcBool	force = FcFalse;
+@@ -369,13 +379,19 @@ main (int argc, char **argv)
+ 	fprintf(stderr, "Cannot malloc\n");
+ 	return 1;
+     }
+-	
++
++    updateDirs = FcStrSetCreate ();
+     changed = 0;
+-    ret = scanDirs (list, config, force, really_force, verbose, FcTrue, &changed);
++    ret = scanDirs (list, config, force, really_force, verbose, FcTrue, &changed, updateDirs);
+     /* 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);
++    list = FcStrListCreate (updateDirs);
++    if (list)
++    {
++	ret += scanDirs (list, config, FcTrue, really_force, verbose, FcFalse, &changed, NULL);
++	FcStrListDone (list);
++    }
++    FcStrSetDestroy (updateDirs);
+ 
+     /*
+      * Try to create CACHEDIR.TAG anyway.
+diff -pruN fontconfig-2.11.0.orig/fontconfig/fontconfig.h fontconfig-2.11.0/fontconfig/fontconfig.h
+--- fontconfig-2.11.0.orig/fontconfig/fontconfig.h	2013-10-11 13:27:42.000000000 +0900
++++ fontconfig-2.11.0/fontconfig/fontconfig.h	2014-07-08 12:37:59.000000000 +0900
+@@ -541,6 +541,9 @@ FcDirSave (FcFontSet *set, FcStrSet *dir
+ 
+ FcPublic FcCache *
+ FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file);
++
++FcPublic FcCache *
++FcDirCacheRescan (const FcChar8 *dir, FcConfig *config);
+     
+ FcPublic FcCache *
+ FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config);
+diff -pruN fontconfig-2.11.0.orig/src/fccache.c fontconfig-2.11.0/src/fccache.c
+--- fontconfig-2.11.0.orig/src/fccache.c	2013-10-11 12:10:18.000000000 +0900
++++ fontconfig-2.11.0/src/fccache.c	2014-07-08 12:39:27.000000000 +0900
+@@ -544,6 +544,26 @@ FcCacheTimeValid (FcCache *cache, struct
+     return cache->checksum == (int) dir_stat->st_mtime;
+ }
+ 
++static FcBool
++FcCacheDirsValid (FcCache *cache)
++{
++    FcStrSet *dirs = FcStrSetCreate ();
++    FcBool ret = FcFalse;
++
++    if (!dirs)
++	goto bail;
++    if (!FcDirScanOnly (dirs, FcCacheDir (cache)))
++	goto bail1;
++    ret = cache->dirs_count == dirs->num;
++    if (FcDebug () & FC_DBG_CACHE)
++	printf ("%s: cache: %d, fs: %d\n", FcCacheDir (cache), cache->dirs_count, dirs->num);
++
++bail1:
++    FcStrSetDestroy (dirs);
++bail:
++    return ret;
++}
++
+ /*
+  * Map a cache file into memory
+  */
+@@ -558,7 +578,8 @@ FcDirCacheMapFd (int fd, struct stat *fd
+     cache = FcCacheFindByStat (fd_stat);
+     if (cache)
+     {
+-	if (FcCacheTimeValid (cache, dir_stat))
++	if (FcCacheTimeValid (cache, dir_stat) &&
++	    FcCacheDirsValid (cache))
+ 	    return cache;
+ 	FcDirCacheUnload (cache);
+ 	cache = NULL;
+@@ -610,6 +631,7 @@ FcDirCacheMapFd (int fd, struct stat *fd
+ 	cache->version < FC_CACHE_CONTENT_VERSION ||
+ 	cache->size != (intptr_t) fd_stat->st_size ||
+ 	!FcCacheTimeValid (cache, dir_stat) ||
++	!FcCacheDirsValid (cache) ||
+ 	!FcCacheInsert (cache, fd_stat))
+     {
+ 	if (allocated)
+@@ -827,6 +849,19 @@ bail1:
+     return NULL;
+ }
+ 
++FcCache *
++FcDirCacheRebuild (FcCache *cache, struct stat *dir_stat, FcStrSet *dirs)
++{
++    FcCache *new;
++    FcFontSet *set = FcFontSetDeserialize (FcCacheSet (cache));
++    const FcChar8 *dir = FcCacheDir (cache);
++
++    new = FcDirCacheBuild (set, dir, dir_stat, dirs);
++    FcFontSetDestroy (set);
++
++    return new;
++}
++
+ /* write serialized state to the cache file */
+ FcBool
+ FcDirCacheWrite (FcCache *cache, FcConfig *config)
+diff -pruN fontconfig-2.11.0.orig/src/fcdir.c fontconfig-2.11.0/src/fcdir.c
+--- fontconfig-2.11.0.orig/src/fcdir.c	2013-10-11 12:10:18.000000000 +0900
++++ fontconfig-2.11.0/src/fcdir.c	2014-07-08 12:39:27.000000000 +0900
+@@ -130,7 +130,12 @@ FcFileScanConfig (FcFontSet	*set,
+     if (FcFileIsDir (file))
+ 	return FcStrSetAdd (dirs, file);
+     else
+-	return FcFileScanFontConfig (set, blanks, file, config);
++    {
++	if (set)
++	    return FcFileScanFontConfig (set, blanks, file, config);
++	else
++	    return FcTrue;
++    }
+ }
+ 
+ FcBool
+@@ -159,7 +164,8 @@ FcDirScanConfig (FcFontSet	*set,
+ 		 FcBlanks	*blanks,
+ 		 const FcChar8	*dir,
+ 		 FcBool		force, /* XXX unused */
+-		 FcConfig	*config)
++		 FcConfig	*config,
++		 FcBool		scanOnly)
+ {
+     DIR			*d;
+     struct dirent	*e;
+@@ -175,7 +181,7 @@ FcDirScanConfig (FcFontSet	*set,
+     if (!set && !dirs)
+ 	return FcTrue;
+ 
+-    if (!blanks)
++    if (!blanks && !scanOnly)
+ 	blanks = FcConfigGetBlanks (config);
+ 
+     /* freed below */
+@@ -228,7 +234,17 @@ FcDirScanConfig (FcFontSet	*set,
+      * Scan file files to build font patterns
+      */
+     for (i = 0; i < files->num; i++)
+-	FcFileScanConfig (set, dirs, blanks, files->strs[i], config);
++    {
++	if (scanOnly)
++	{
++	    if (FcFileIsDir (files->strs[i]))
++		FcStrSetAdd (dirs, files->strs[i]);
++	}
++	else
++	{
++	    FcFileScanConfig (set, dirs, blanks, files->strs[i], config);
++	}
++    }
+ 
+ bail2:
+     FcStrSetDestroy (files);
+@@ -252,7 +268,14 @@ FcDirScan (FcFontSet	    *set,
+     if (cache || !force)
+ 	return FcFalse;
+ 
+-    return FcDirScanConfig (set, dirs, blanks, dir, force, FcConfigGetCurrent ());
++    return FcDirScanConfig (set, dirs, blanks, dir, force, FcConfigGetCurrent (), FcFalse);
++}
++
++FcBool
++FcDirScanOnly (FcStrSet		*dirs,
++	       const FcChar8	*dir)
++{
++    return FcDirScanConfig (NULL, dirs, NULL, dir, FcTrue, NULL, FcTrue);
+ }
+ 
+ /*
+@@ -283,7 +306,7 @@ FcDirCacheScan (const FcChar8 *dir, FcCo
+     /*
+      * Scan the dir
+      */
+-    if (!FcDirScanConfig (set, dirs, NULL, dir, FcTrue, config))
++    if (!FcDirScanConfig (set, dirs, NULL, dir, FcTrue, config, FcFalse))
+ 	goto bail2;
+ 
+     /*
+@@ -306,6 +329,45 @@ FcDirCacheScan (const FcChar8 *dir, FcCo
+     return cache;
+ }
+ 
++FcCache *
++FcDirCacheRescan (const FcChar8 *dir, FcConfig *config)
++{
++    FcCache *cache = FcDirCacheLoad (dir, config, NULL);
++    FcCache *new = NULL;
++    struct stat dir_stat;
++    FcStrSet *dirs;
++
++    if (!cache)
++	return NULL;
++    if (FcStatChecksum (dir, &dir_stat) < 0)
++	goto bail;
++    dirs = FcStrSetCreate ();
++    if (!dirs)
++	goto bail;
++
++    /*
++     * Scan the dir
++     */
++    if (!FcDirScanConfig (NULL, dirs, NULL, dir, FcTrue, config, FcFalse))
++	goto bail1;
++    /*
++     * Rebuild the cache object
++     */
++    new = FcDirCacheRebuild (cache, &dir_stat, dirs);
++    if (!new)
++	goto bail1;
++    FcDirCacheUnload (cache);
++    /*
++     * Write out the cache file, ignoring any troubles
++     */
++    FcDirCacheWrite (new, config);
++
++bail1:
++    FcStrSetDestroy (dirs);
++bail:
++    return new;
++}
++
+ /*
+  * Read (or construct) the cache for a directory
+  */
+diff -pruN fontconfig-2.11.0.orig/src/fcfs.c fontconfig-2.11.0/src/fcfs.c
+--- fontconfig-2.11.0.orig/src/fcfs.c	2013-10-11 12:10:18.000000000 +0900
++++ fontconfig-2.11.0/src/fcfs.c	2014-07-08 12:37:59.000000000 +0900
+@@ -122,6 +122,28 @@ FcFontSetSerialize (FcSerialize *seriali
+ 
+     return s_serialize;
+ }
++
++FcFontSet *
++FcFontSetDeserialize (const FcFontSet *set)
++{
++    int i;
++    FcFontSet *new = FcFontSetCreate ();
++
++    if (!new)
++	return NULL;
++    for (i = 0; i < set->nfont; i++)
++    {
++	if (!FcFontSetAdd (new, FcPatternDuplicate (FcFontSetFont (set, i))))
++	    goto bail;
++    }
++
++    return new;
++bail:
++    FcFontSetDestroy (new);
++
++    return NULL;
++}
++
+ #define __fcfs__
+ #include "fcaliastail.h"
+ #undef __fcfs__
+diff -pruN fontconfig-2.11.0.orig/src/fcint.h fontconfig-2.11.0/src/fcint.h
+--- fontconfig-2.11.0.orig/src/fcint.h	2013-10-11 12:10:18.000000000 +0900
++++ fontconfig-2.11.0/src/fcint.h	2014-07-08 12:39:27.000000000 +0900
+@@ -567,6 +567,9 @@ FcDirCacheScan (const FcChar8 *dir, FcCo
+ FcPrivate FcCache *
+ FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, struct stat *dir_stat, FcStrSet *dirs);
+ 
++FcPrivate FcCache *
++FcDirCacheRebuild (FcCache *cache, struct stat *dir_stat, FcStrSet *dirs);
++
+ FcPrivate FcBool
+ FcDirCacheWrite (FcCache *cache, FcConfig *config);
+ 
+@@ -824,7 +827,12 @@ FcDirScanConfig (FcFontSet	*set,
+ 		 FcBlanks	*blanks,
+ 		 const FcChar8	*dir,
+ 		 FcBool		force,
+-		 FcConfig	*config);
++		 FcConfig	*config,
++		 FcBool		scanOnly);
++
++FcPrivate FcBool
++FcDirScanOnly (FcStrSet		*dirs,
++	       const FcChar8	*dir);
+ 
+ /* fcfont.c */
+ FcPrivate int
+@@ -838,6 +846,9 @@ FcFontSetSerializeAlloc (FcSerialize *se
+ FcPrivate FcFontSet *
+ FcFontSetSerialize (FcSerialize *serialize, const FcFontSet * s);
+ 
++FcPrivate FcFontSet *
++FcFontSetDeserialize (const FcFontSet *set);
++
+ /* fchash.c */
+ FcPrivate FcChar8 *
+ FcHashGetSHA256Digest (const FcChar8 *input_strings,
+diff -pruN fontconfig-2.11.0.orig/src/fcpat.c fontconfig-2.11.0/src/fcpat.c
+--- fontconfig-2.11.0.orig/src/fcpat.c	2013-10-11 12:10:18.000000000 +0900
++++ fontconfig-2.11.0/src/fcpat.c	2014-07-08 12:37:59.000000000 +0900
+@@ -33,6 +33,7 @@ FcPatternCreate (void)
+     p = (FcPattern *) malloc (sizeof (FcPattern));
+     if (!p)
+ 	return 0;
++    memset (p, 0, sizeof (FcPattern));
+     p->num = 0;
+     p->size = 0;
+     p->elts_offset = FcPtrToOffset (p, NULL);
+@@ -1310,6 +1311,7 @@ FcValueListSerialize (FcSerialize *seria
+     }
+     return head_serialized;
+ }
++
+ #define __fcpat__
+ #include "fcaliastail.h"
+ #include "fcftaliastail.h"
diff --git a/fontconfig.spec b/fontconfig.spec
index b0a6bac..1bd3fdc 100644
--- a/fontconfig.spec
+++ b/fontconfig.spec
@@ -3,7 +3,7 @@
 Summary:	Font configuration and customization library
 Name:		fontconfig
 Version:	2.11.0
-Release:	1%{?dist}
+Release:	2%{?dist}
 # src/ftglue.[ch] is in Public Domain
 # src/fccache.c contains Public Domain code
 # fc-case/CaseFolding.txt is in the UCD
@@ -16,6 +16,7 @@ Source1:	25-no-bitmap-fedora.conf
 
 # https://bugzilla.redhat.com/show_bug.cgi?id=140335
 Patch0:		fontconfig-sleep-less.patch
+Patch1:		fontconfig-fix-race-condition.patch
 
 BuildRequires:	expat-devel
 BuildRequires:	freetype-devel >= %{freetype_version}
@@ -57,6 +58,7 @@ which is useful for developing applications that uses fontconfig.
 %prep
 %setup -q
 %patch0 -p1 -b .sleep-less
+%patch1 -p1 -b .race
 
 %build
 # We don't want to rebuild the docs, but we want to install the included ones.
@@ -133,6 +135,9 @@ fi
 %doc fontconfig-devel.txt fontconfig-devel
 
 %changelog
+* Tue Jul  8 2014 Akira TAGOH <tagoh at redhat.com> - 2.11.0-2
+- Fix the race condition issue on updating caches. (#921706)
+
 * Fri Oct 11 2013 Akira TAGOH <tagoh at redhat.com> - 2.11.0-1
 - New upstream release.
 


More information about the scm-commits mailing list