Bug 100096

Summary: fontconfig update racy, causes update storm that freezes the desktop
Product: fontconfig Reporter: Jan Alexander Steffens (heftig) <jan.steffens>
Component: libraryAssignee: fontconfig-bugs
Status: RESOLVED FIXED QA Contact: Behdad Esfahbod <freedesktop>
Severity: normal    
Priority: medium CC: akira, dr.khaled.hosny
Version: 2.12   
Hardware: All   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Bug Depends on: 64766    
Bug Blocks:    

Description Jan Alexander Steffens (heftig) 2017-03-07 08:12:22 UTC
Already posted as a gnome-settings-daemon bug at https://bugzilla.gnome.org/show_bug.cgi?id=777255

I'm trying to debug my desktop freezing often when I update fonts, and I think I managed to reduce it to this:

1. Something changes ~/.local/share/fonts.

2. GSD notices and reinitializes fontconfig, which updates the cache.

3. GSD sends out an XSettings update.

2. Something changes ~/.local/share/fonts, again.

3. All other Gtk processes receive the XSettings update and reinitialize fontconfig.  This includes the shell.

4. The processes all discover that ~/.local/share/fonts has changed and attempt to update the cache. This needs a lock on the cache.

5. The processes wait on the lock, one by one rescanning the fonts in the dir.

Since the shell takes part, the desktop is frozen until the shell has finished its rebuild. If the dir contains a lot of fonts and is slow to scan, the desktop can be frozen for quite a while.

Running "touch abc; sleep 0.1; rm abc" in ~/.local/share/fonts quite reliably freezes the shell for a second. Doing this in /usr/share/fonts/noto/ (which contains the entire Noto set including CJK) freezes the desktop for over two and a half minutes.

Maybe fontconfig can at least reduce the impact by rechecking whether the cache is up-to-date after acquiring the lock? This way there should be only one unexpected cache update instead of a dozen or more.

gnome-settings-daemon 3.22.1, GTK 3.22.6, fontconfig 2.12.1
Comment 1 Akira TAGOH 2017-07-30 10:27:00 UTC
(In reply to Jan Alexander Steffens (heftig) from comment #0)
> Maybe fontconfig can at least reduce the impact by rechecking whether the
> cache is up-to-date after acquiring the lock?

Maybe not possible. that is why this is racy. one who knows the targeted directories is updated is only one or a few where is kicking updates. but it isn't necessarily true that the updated caches contains the updates coming during updating.

>                                               This way there should be only
> one unexpected cache update instead of a dozen or more.

Thus this isn't true.
If the updates on fonts directories is often happening, maybe good to increase the rescan interval in the config to check. other option is to implement a feature stops updating caches in fontconfig during loading caches. this will prevents unexpected freeze on runtime. but someone needs to take care of the outdated caches instead of fontconfig and re-create caches as needed then.
Comment 2 Akira TAGOH 2017-07-31 14:43:04 UTC
One proposed implementation: https://cgit.freedesktop.org/~tagoh/fontconfig/commit/?h=disable-auto-update

On this way, most applications turns off the cache updates on loading and have a process to update. in this case, GSD. once updates is done, GSD could notifies to applications to force-reload caches.
Comment 3 Jan Alexander Steffens (heftig) 2017-07-31 15:17:25 UTC
(In reply to Akira TAGOH from comment #1)
> Maybe not possible. that is why this is racy. one who knows the targeted
> directories is updated is only one or a few where is kicking updates. but it
> isn't necessarily true that the updated caches contains the updates coming
> during updating.

I wasn't looking for a perfect solution. Note that in my tests I was only touching one directory twice within 100ms, yet every process loading fontconfig insisted on regenerating the cache for this directory in sequence, taking over two minutes in total. The second regeneration should have been the last (for the latter change), but it wasn't.

> If the updates on fonts directories is often happening, maybe good to
> increase the rescan interval in the config to check.

I think this would make it happen less often, but still just as badly.

> other option is to
> implement a feature stops updating caches in fontconfig during loading
> caches. this will prevents unexpected freeze on runtime. but someone needs
> to take care of the outdated caches instead of fontconfig and re-create
> caches as needed then.

Right. The perfect solution for me would be:

- libfontconfig only watches config and caches for changes, never font dirs
- system caches are only ever regenerated manually (e.g
 via package manager)
- user caches are regenerated manually or by gnome-settings-daemon when user fonts change

This should totally avoid unexpected stalls because the applications do not attempt to scan the fonts. However, I don't know how to deal with apps that need older cache versions not produced by the system.

Another mitigation approach would be doing the scanning asynchronously, in a worker thread.
Comment 4 Akira TAGOH 2018-03-26 07:57:02 UTC
I suppose this should be improved by 2.13.0. please test and see if that fix is good enough.
Comment 5 Jan Alexander Steffens (heftig) 2018-03-26 18:04:37 UTC
Yep, I still get minor hiccups but it looks good enough, thanks.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.