diff --git a/src/fccache.c b/src/fccache.c
index 0976201..4acde22 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -338,7 +338,7 @@ FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat)
 static FcBool
 FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
 		   FcBool (*callback) (FcConfig *config, int fd, struct stat *fd_stat,
-				       struct stat *dir_stat, void *closure),
+				       struct stat *dir_stat, struct timeval *cache_mtime, void *closure),
 		   void *closure, FcChar8 **cache_file_ret)
 {
     int		fd = -1;
@@ -348,6 +348,7 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
     struct stat file_stat, dir_stat;
     FcBool	ret = FcFalse;
     const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+    struct timeval latest_mtime = (struct timeval){ 0 };
 
     if (sysroot)
 	d = FcStrBuildFilename (sysroot, dir, NULL);
@@ -383,15 +384,18 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
 #endif
         fd = FcDirCacheOpenFile (cache_hashed, &file_stat);
         if (fd >= 0) {
-	    ret = (*callback) (config, fd, &file_stat, &dir_stat, closure);
+	    ret = (*callback) (config, fd, &file_stat, &dir_stat, &latest_mtime, closure);
 	    close (fd);
 	    if (ret)
 	    {
 		if (cache_file_ret)
+		{
+		    if (*cache_file_ret)
+			FcStrFree (*cache_file_ret);
 		    *cache_file_ret = cache_hashed;
+		}
 		else
 		    FcStrFree (cache_hashed);
-		break;
 	    }
 	}
 #ifndef _WIN32
@@ -414,7 +418,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
 	    }
 	}
 #endif
-    	FcStrFree (cache_hashed);
+	else
+	    FcStrFree (cache_hashed);
     }
     FcStrListDone (list);
 
@@ -998,12 +1003,31 @@ FcDirCacheUnload (FcCache *cache)
 }
 
 static FcBool
-FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
+FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, struct timeval *latest_cache_mtime, void *closure)
 {
     FcCache *cache = FcDirCacheMapFd (config, fd, fd_stat, dir_stat);
+    struct timeval cache_mtime;
 
     if (!cache)
 	return FcFalse;
+    cache_mtime.tv_sec = fd_stat->st_mtime;
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+    cache_mtime.tv_usec = fd_stat->st_mtim.tv_nsec / 1000;
+#else
+    cache_mtime.tv_usec = 0;
+#endif
+    if (timercmp (latest_cache_mtime, &cache_mtime, <))
+    {
+	if (*((FcCache **) closure))
+	    FcDirCacheUnload (*((FcCache **) closure));
+    }
+    else
+    {
+	FcDirCacheUnload (cache);
+	return FcFalse;
+    }
+    latest_cache_mtime->tv_sec = cache_mtime.tv_sec;
+    latest_cache_mtime->tv_usec = cache_mtime.tv_usec;
     *((FcCache **) closure) = cache;
     return FcTrue;
 }
@@ -1093,7 +1117,7 @@ FcDirChecksumNano (struct stat *statb)
  * the magic number and the size field
  */
 static FcBool
-FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure FC_UNUSED)
+FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, struct timeval *latest_cache_mtime, void *closure FC_UNUSED)
 {
     FcBool  ret = FcTrue;
     FcCache	c;
diff --git a/test/run-test.sh b/test/run-test.sh
index 4e5968b..8ad09e3 100644
--- a/test/run-test.sh
+++ b/test/run-test.sh
@@ -340,6 +340,72 @@ fi
 
 rm -rf $MyPWD/sysroot
 
+dotest "read newer caches when multiple places are allowed to store"
+prep
+cp $FONT1 $FONT2 $FONTDIR
+if [ -n ${SOURCE_DATE_EPOCH:-} ] && [ ${#SOURCE_DATE_EPOCH} -gt 0 ]; then
+    touch -m -t "`date -d \"@${SOURCE_DATE_EPOCH}\" +%y%m%d%H%M.%S`" $FONTDIR
+fi
+MYCACHEBASEDIR=`mktemp -d /tmp/fontconfig.XXXXXXXX`
+MYCACHEDIR=$MYCACHEBASEDIR/cache.dir
+MYOWNCACHEDIR=$MYCACHEBASEDIR/owncache.dir
+MYCONFIG=`mktemp /tmp/fontconfig.XXXXXXXX`
+
+mkdir -p $MYCACHEDIR
+mkdir -p $MYOWNCACHEDIR
+
+sed "s!@FONTDIR@!$FONTDIR!
+s!@REMAPDIR@!!
+s!@CACHEDIR@!$MYCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf
+
+FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCCACHE $FONTDIR
+
+sleep 1
+cat<<EOF>$MYCONFIG
+<fontconfig>
+  <match target="scan">
+    <test name="file"><string>$FONTDIR/4x6.pcf</string></test>
+    <edit name="pixelsize"><int>8</int></edit>
+  </match>
+</fontconfig>
+EOF
+sed "s!@FONTDIR@!$FONTDIR!
+s!@REMAPDIR@!<include ignore_missing=\"yes\">$MYCONFIG</include>!
+s!@CACHEDIR@!$MYOWNCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf
+
+if [ -n ${SOURCE_DATE_EPOCH:-} ]; then
+  old_epoch=${SOURCE_DATE_EPOCH}
+  SOURCE_DATE_EPOCH=`expr $SOURCE_DATE_EPOCH + 1`
+fi
+FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCCACHE -f $FONTDIR
+if [ -n ${SOURCE_DATE_EPOCH:-} ]; then
+  SOURCE_DATE_EPOCH=${old_epoch}
+fi
+
+sed "s!@FONTDIR@!$FONTDIR!
+s!@REMAPDIR@!<include ignore_missing=\"yes\">$MYCONFIG</include>!
+s!@CACHEDIR@!$MYCACHEDIR</cachedir><cachedir>$MYOWNCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf
+
+FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort > my-out
+echo "=" >> my-out
+FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort >> my-out
+echo "=" >> my-out
+FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort >> my-out
+tr -d '\015' <my-out >my-out.tmp; mv my-out.tmp my-out
+sed -e 's/pixelsize=6/pixelsize=8/g' $BUILDTESTDIR/$EXPECTED > my-out.expected
+
+if cmp my-out my-out.expected > /dev/null ; then : ; else
+    echo "*** Test failed: $TEST"
+    echo "*** output is in 'my-out', expected output in 'my-out.expected'"
+    echo "Actual Result"
+    cat my-out
+    echo "Expected Result"
+    cat my-out.expected
+    exit 1
+fi
+
+rm -rf $MYCACHEBASEDIR $MYCONFIG my-fonts.conf my-out my-out.expected
+
 fi # if [ "x$EXEEXT" = "x" ]
 
 rm -rf $FONTDIR $CACHEFILE $CACHEDIR $BASEDIR $FONTCONFIG_FILE out
-- 
2.24.1
 
From a45fc8a33256d9d3ea0ea7947f33c8e5e3cc7238 Mon Sep 17 00:00:00 2001
From: Akira TAGOH <akira@tagoh.org>
Date: Thu, 31 Oct 2019 16:15:25 +0900
Subject: [PATCH 2/9] Fix a memory leak caused by the previous commit
 
---
 src/fccache.c | 4 ++++
 1 file changed, 4 insertions(+)
 
diff --git a/src/fccache.c b/src/fccache.c
index 4acde22..c565560 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -397,6 +397,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
 		else
 		    FcStrFree (cache_hashed);
 	    }
+	    else
+		FcStrFree (cache_hashed);
 	}
 #ifndef _WIN32
 	else if (!retried)
@@ -416,6 +418,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
 		    break;
 		goto retry;
 	    }
+	    else
+		FcStrFree (cache_hashed);
 	}
 #endif
 	else
-- 
2.24.1
