Fontconfig: Replace FcInitReinitialize with FcInitLoadConfigAndFonts 52/319652/1
authorANZ1217 <chihun.jeong@samsung.com>
Wed, 12 Feb 2025 05:33:17 +0000 (14:33 +0900)
committerANZ1217 <chihun.jeong@samsung.com>
Fri, 14 Feb 2025 06:50:19 +0000 (15:50 +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: I5b4538eb1a309736fe1a862047aa660a7143da47

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 501bc5c5eaef9da7468f25c73d8491f56be4f002..a0bc875ab56f7576668f9abdd01463fc2abeb7c6 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 5f4f0fd1e2deef1b5bb32a0613e08f26beb3a157..cb7617763504d5972dc2aa883c5834d8e850029f 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 cae1eb4b8a64196abc23f844508a074e760935ee..b781937cddadb220e84bdc65f97e78bc40dbfa88 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()));