Fontconfig: Replace FcInitReinitialize with FcInitLoadConfigAndFonts 10/319510/4
authorANZ1217 <chihun.jeong@samsung.com>
Wed, 12 Feb 2025 05:33:17 +0000 (14:33 +0900)
committerANZ1217 <chihun.jeong@samsung.com>
Thu, 13 Feb 2025 06:03:07 +0000 (15:03 +0900)
FcInitReinitialize() causes global font cache and config reload.
which may lead to race conditions and crashes.
Replaced it with FcInitLoadConfigAndFonts() to safely reload config within the current process without affecting others.

Change-Id: Ic5c911f399de141310e99711ae72db64c9dad3cd

dali/internal/text/text-abstraction/plugin/font-client-plugin-cache-handler.cpp
dali/internal/text/text-abstraction/plugin/font-client-plugin-cache-handler.h
dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp

index 88409683c09d6717619dfec5ecf3e937b270b4dc..7f61aa97e6e38c45a3f3cbeb97bd983ec513b607 100644 (file)
@@ -563,7 +563,26 @@ void FontClient::Plugin::CacheHandler::InitDefaultFontDescription()
     ClearCharacterSet();
 
     // FcInitBringUptoDate did not seem to reload config file as was still getting old default font.
-    FcInitReinitialize();
+    // FcInitReinitialize resets global Fonconfig state and cache, which can cause race conditions or double free.
+    // FcInitLoadConfigAndFonts sets the current default configuration for the library, which is specific to the calling process.
+
+    FcConfig* newConfig = FcInitLoadConfigAndFonts();
+
+    if(newConfig)
+    {
+      for(auto &path: mCustomFontDirectories)
+      {
+        FcConfigAppFontAddDir(newConfig, reinterpret_cast<const FcChar8*>(path.c_str()));
+      }
+
+      FcConfigBuildFonts(newConfig);
+      FcConfigSetCurrent(newConfig);
+      FcConfigDestroy(newConfig);
+    }
+    else
+    {
+      DALI_LOG_ERROR("Can't init font config library\n");
+    }
 
     FcPattern* matchPattern = FcPatternCreate(); // Creates a pattern that needs to be destroyed by calling FcPatternDestroy.
 
@@ -609,7 +628,7 @@ void FontClient::Plugin::CacheHandler::InitDefaultFontDescription()
       FcPatternDestroy(matchPattern);
     }
 
-    // Create again the character sets as they are not valid after FcInitReinitialize()
+    // Create again the character sets as they are not valid after FcInitLoadConfigAndFonts()
     CreateCharacterSet();
   }
 }
index bb541cc5c4ee61ece85364ecacaa9e0987a989a2..5541a56cc8f9b7544568191be3663462a25a14b5 100644 (file)
@@ -483,6 +483,8 @@ public:                                    // Cache container list
   std::vector<PixelBufferCacheItem> mPixelBufferCache;  ///< Caches the pixel buffer of a url.
   std::vector<EmbeddedItem>         mEmbeddedItemCache; ///< Cache embedded items.
 
+  std::vector<std::string> mCustomFontDirectories;  ///< Cache custom font directories to recovery upon reinitialization.
+
 private:                                                 // Member value
   std::unique_ptr<GlyphCacheManager> mGlyphCacheManager; ///< The glyph cache manager. It will cache this face's glyphs.
 
index 07faea866dadf7de5cd5cd193d10b26851bbc33c..62ad960c983a7de9fab507426fbc218713a681d0 100644 (file)
@@ -1076,6 +1076,11 @@ bool FontClient::Plugin::AddCustomFontDirectory(const FontPath& path)
       mCustomFonts.clear();
     }
     mCustomFonts.push_back(path);
+
+    if(mCacheHandler)
+    {
+      mCacheHandler->mCustomFontDirectories.push_back(path);
+    }
   }
   // nullptr as first parameter means the current configuration is used.
   return FcConfigAppFontAddDir(nullptr, reinterpret_cast<const FcChar8*>(path.c_str()));