Add global fontconfig lock.
authorcommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 31 Mar 2014 18:41:30 +0000 (18:41 +0000)
committercommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 31 Mar 2014 18:41:30 +0000 (18:41 +0000)
BUG=skia:2255, skia:1497
NOTRY=true
R=bungeman@google.com, mtklein@google.com

Author: mtklein@chromium.org

Review URL: https://codereview.chromium.org/219613003

git-svn-id: http://skia.googlecode.com/svn/trunk@13998 2bbb7eff-a529-9590-31e7-b0007b416f81

src/fonts/SkFontMgr_fontconfig.cpp

index bd4c8dd..1d17111 100644 (file)
 #include "SkMath.h"
 #include "SkString.h"
 #include "SkTDArray.h"
+#include "SkThread.h"
 
 // for now we pull these in directly. eventually we will solely rely on the
 // SkFontConfigInterface instance.
 #include <fontconfig/fontconfig.h>
 #include <unistd.h>
 
+namespace {
+
+// Fontconfig is not threadsafe before 2.10.91.  Before that, we lock with a global mutex.
+// See skia:1497 for background.
+SK_DECLARE_STATIC_MUTEX(gFCMutex);
+static bool gFCSafeToUse;
+
+struct FCLocker {
+    FCLocker() {
+        if (FcGetVersion() < 21091) {  // We assume FcGetVersion() has always been thread safe.
+            gFCMutex.acquire();
+            fUnlock = true;
+        } else {
+            fUnlock = false;
+        }
+        gFCSafeToUse = true;
+    }
+
+    ~FCLocker() {
+        gFCSafeToUse = false;
+        if (fUnlock) {
+            gFCMutex.release();
+        }
+    }
+
+private:
+    bool fUnlock;
+};
+
+} // namespace
+
+
 // Defined in SkFontHost_FreeType.cpp
 bool find_name_and_attributes(SkStream* stream, SkString* name,
                               SkTypeface::Style* style, bool* isFixedWidth);
@@ -40,6 +73,7 @@ static bool is_lower(char c) {
 }
 
 static int get_int(FcPattern* pattern, const char field[]) {
+    SkASSERT(gFCSafeToUse);
     int value;
     if (FcPatternGetInteger(pattern, field, 0, &value) != FcResultMatch) {
         value = SK_MinS32;
@@ -48,6 +82,7 @@ static int get_int(FcPattern* pattern, const char field[]) {
 }
 
 static const char* get_name(FcPattern* pattern, const char field[]) {
+    SkASSERT(gFCSafeToUse);
     const char* name;
     if (FcPatternGetString(pattern, field, 0, (FcChar8**)&name) != FcResultMatch) {
         name = "";
@@ -56,6 +91,7 @@ static const char* get_name(FcPattern* pattern, const char field[]) {
 }
 
 static bool valid_pattern(FcPattern* pattern) {
+    SkASSERT(gFCSafeToUse);
     FcBool is_scalable;
     if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch || !is_scalable) {
         return false;
@@ -208,6 +244,8 @@ protected:
     }
 
     virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
+        FCLocker lock;
+
         FcPattern* pattern = FcPatternCreate();
 
         FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
@@ -284,6 +322,7 @@ protected:
 
     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
                                                unsigned styleBits) const SK_OVERRIDE {
+        FCLocker lock;
         return FontConfigTypeface::LegacyCreateTypeface(NULL, familyName,
                                                   (SkTypeface::Style)styleBits);
     }