Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c703178

Browse filesBrowse files
authored
Merge pull request #14535 from anntzer/ft2fontfork
Invalidate FT2Font cache when fork()ing.
2 parents c0a6527 + f1eeeab commit c703178
Copy full SHA for c703178

File tree

Expand file treeCollapse file tree

2 files changed

+24
-1
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+24
-1
lines changed

‎lib/matplotlib/font_manager.py

Copy file name to clipboardExpand all lines: lib/matplotlib/font_manager.py
+9-1Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1264,12 +1264,20 @@ def is_opentype_cff_font(filename):
12641264
return False
12651265

12661266

1267-
_get_font = lru_cache(64)(ft2font.FT2Font)
12681267
_fmcache = os.path.join(
12691268
mpl.get_cachedir(), 'fontlist-v{}.json'.format(FontManager.__version__))
12701269
fontManager = None
12711270

12721271

1272+
_get_font = lru_cache(64)(ft2font.FT2Font)
1273+
# FT2Font objects cannot be used across fork()s because they reference the same
1274+
# FT_Library object. While invalidating *all* existing FT2Fonts after a fork
1275+
# would be too complicated to be worth it, the main way FT2Fonts get reused is
1276+
# via the cache of _get_font, which we can empty upon forking (in Py3.7+).
1277+
if hasattr(os, "register_at_fork"):
1278+
os.register_at_fork(after_in_child=_get_font.cache_clear)
1279+
1280+
12731281
def get_font(filename, hinting_factor=None):
12741282
if hinting_factor is None:
12751283
hinting_factor = rcParams['text.hinting_factor']

‎lib/matplotlib/tests/test_font_manager.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_font_manager.py
+15Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from io import BytesIO
2+
import multiprocessing
23
import os
34
from pathlib import Path
45
import shutil
@@ -184,3 +185,17 @@ def test_user_fonts_win32():
184185
# Now, the font should be available
185186
fonts = findSystemFonts()
186187
assert any(font_test_file in font for font in fonts)
188+
189+
190+
def _model_handler(_):
191+
fig, ax = plt.subplots()
192+
fig.savefig(BytesIO(), format="pdf")
193+
plt.close()
194+
195+
196+
@pytest.mark.skipif(not hasattr(os, "register_at_fork"),
197+
reason="Cannot register at_fork handlers")
198+
def test_fork():
199+
_model_handler(0) # Make sure the font cache is filled.
200+
ctx = multiprocessing.get_context("fork")
201+
ctx.Pool(processes=2).map(_model_handler, range(2))

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.