NEW325185
[GTK][WPE][Skia] Web process spins at 100% CPU forever in SkFontMgr_fontconfig GetFamilyNames() when fontconfig lists a font without a family
https://bugs.webkit.org/show_bug.cgi?id=325185
Summary [GTK][WPE][Skia] Web process spins at 100% CPU forever in SkFontMgr_fontconfi...
vasiliji.markin
Reported 2026-09-24 13:08:11 PDT
With libwebkit2gtk-4.1-0 2.52.6 (Ubuntu 26.04) both WebKitWebProcess processes of an app (Handy 0.9.7, a Tauri app) used one full core each from the start, forever: 5 h 31 min of CPU time in 5 h 32 min, no voluntary context switches while watched. The loop runs inside the WebPage constructor, so the pages never finish loading. The same code is in WebKit main (Source/ThirdParty/skia) and in Skia main. Stack (perf, symbols from debuginfod.ubuntu.com): FcPatternGetString SkFontMgr_fontconfig::GetFamilyNames(FcConfig*) SkFontMgr_fontconfig.cpp:648 SkFontMgr_New_FontConfig SkFontMgr_fontconfig.cpp:993 WebCore::FontCache::fontManager() const FontCacheSkia.cpp:70 WebCore::FontCache::createFontPlatformData WebCore::FontCache::cachedFontPlatformData WebCore::FontCache::fontForFamily WebCore::CSSFontSelector::fontRangesForFamily WebCore::FontCascadeFonts::realizeFallbackRangesAt / primaryFont WebCore::Style::Resolver::initialize WebCore::Document::resolveStyle <- Document::finishedParsing WebCore::DocumentLoader::maybeLoadEmpty WebKit::WebPage::WebPage <- WebKit::WebProcess::createWebPage Cause: GetFamilyNames() walks every pattern with for (int id = 0; ; ++id) { FcResult result = FcPatternGetString(current, FC_FAMILY, id, &fcFamilyName); if (FcResultNoId == result) break; if (FcResultMatch != result) continue; For a pattern without any FC_FAMILY element, fontconfig returns FcResultNoMatch for every id (FcResultNoId only when the element exists and id is past its last value), so the loop never ends. FontContainsCharacter() has the same loop over FC_CHARSET. (AnyStringMatching() already caps its loop at 65536 ids.) Checked with a small program against fontconfig 2.17.1: for a pattern with only "file" and "fontwrapper", FcPatternGetString(FC_FAMILY) returns NoMatch for id 0, 1 and 1000; the loop above does not exit within 10 million iterations; the loop in the patch below exits at once and gives the same result as before for normal fonts. Such patterns exist in practice: fontconfig's fontations backend stores a placeholder with only "file" and "fontwrapper" for every WOFF/WOFF2 file, and these reach other fontconfig builds through shared caches. Chrome 154 bundles such a fontconfig and links its cache for the system fontconfig (https://gitlab.freedesktop.org/fontconfig/fontconfig/-/work_items/565), and the font cache in the Kubuntu 26.04.1 image had them too. Here they were the 40 .woff/.woff2 files of fonts-katex. Suggested fix (Source/ThirdParty/skia/src/ports/SkFontMgr_fontconfig.cpp, the same in Skia upstream): --- a/src/ports/SkFontMgr_fontconfig.cpp +++ b/src/ports/SkFontMgr_fontconfig.cpp @@ static sk_sp<SkDataTable> GetFamilyNames(FcConfig* fcconfig) { FcResult result = FcPatternGetString(current, FC_FAMILY, id, &fcFamilyName); - if (FcResultNoId == result) { - break; - } - if (FcResultMatch != result) { + if (FcResultTypeMismatch == result) { continue; } + if (FcResultMatch != result) { + // NoId: no more values; NoMatch: the font has no family at all. + break; + } @@ static bool FontContainsCharacter(FcPattern* font, uint32_t character) { result = FcPatternGetCharSet(font, FC_CHARSET, charSetId, &matchCharSet); - if (FcResultNoId == result) { - break; - } - if (FcResultMatch != result) { + if (FcResultTypeMismatch == result) { continue; } + if (FcResultMatch != result) { + break; + } Workaround for users: a fontconfig <rejectfont> rule for *.woff and *.woff2. (Found with the help of an AI assistant, Claude; the profile, stack and test are from my machine.)
Attachments
Netmonroots
Comment 1 2026-10-03 05:18:14 PDT
Confirmed on Zorin OS 18.1 with WebKitGTK 2.52.6. Symptoms: - Proton Authenticator: completely white WebView - Minimal GTK3/WebKit2 4.1 WebView: completely white - WebKitWebProcess/NetworkProcess started, but the page did not render. fc-match -v selected: file: "/usr/share/fonts/woff/opendyslexic/OpenDyslexic-Bold.woff" fontwrapper: "WOFF" Installed WOFF fonts were: /usr/share/fonts/woff/opendyslexic/OpenDyslexic-Bold.woff /usr/share/fonts/woff/opendyslexic/OpenDyslexic-Italic.woff /usr/share/fonts/woff/opendyslexic/OpenDyslexic-Regular.woff /usr/share/fonts/woff/opendyslexic/OpenDyslexic-BoldItalic.woff Adding a per-user Fontconfig reject rule for *.woff and *.woff2 and rebuilding the Fontconfig cache immediately restored WebKit rendering. After reboot, Proton Authenticator and the minimal WebKitGTK test continued to work normally. Interestingly, Aloha Browser (Chromium/Blink), which had been crashing in RemoteFontFaceSource::CreateLoadingFallbackFontData(), also started working normally after the same Fontconfig change. I am mentioning this only as an observation; I cannot confirm that the Blink issue has the same underlying bug.
Michael Catanzaro
Comment 2 2026-10-07 12:01:12 PDT
*** Bug 326509 has been marked as a duplicate of this bug. ***
Note You need to log in before you can comment on or make changes to this bug.