Skip to content

FreeTypeFont is not thread-safe with free threading #9497

@colesbury

Description

@colesbury

This was originally discovered by a colleague. Using a FreeTypeFont created by ImageFont.truetype(...) from multiple threads crashes.

This looks like a limitation of the freetype library:

https://github.com/freetype/freetype/blob/07d8d50a63a45a7446b2fc44732baecc685f3e4c/docs/CHANGES#L1634-L1635

I think we can use a critical section to lock around operations on a FontObject / FT_Face.

What actually happened?

Segmentation fault

What are your OS, Python and Pillow versions?

  • OS: linux
  • Python: 3.14t
  • Pillow: 12.2.0.dev0
Pillow version:
     Pillow 12.2.0.dev0
     Python 3.14.3+ free-threading build (heads/3.14:fa3143a1d2d, Mar 25 2026, 14:10:06) [Clang 20.1.8 (++20250804090239+87f0227cb601-1~exp1~20250804210352.139)]
     --------------------------------------------------------------------
     Python executable is /home/sgross/cpython/python
     System Python files loaded from /usr/local
     --------------------------------------------------------------------
     Python Pillow modules loaded from /home/sgross/pillow/src/PIL
     Binary Pillow modules loaded from /home/sgross/pillow/src/PIL
     --------------------------------------------------------------------
     --- PIL CORE support ok, compiled for 12.2.0.dev0
     --- TKINTER support ok, loaded 8.6
     --- FREETYPE2 support ok, loaded 2.13.2
     *** LITTLECMS2 support not installed
     *** WEBP support not installed
     *** AVIF support not installed
     --- JPEG support ok, compiled for libjpeg-turbo 2.1.5
     *** OPENJPEG (JPEG2000) support not installed
     --- ZLIB (PNG/ZIP) support ok, loaded 1.3
     *** LIBTIFF support not installed
     *** RAQM (Bidirectional Text) support not installed
     *** LIBIMAGEQUANT (Quantization method) support not installed
     --- XCB (X protocol) support ok
     --------------------------------------------------------------------
import sys
import threading

from PIL import ImageFont

for i in range(10):
    font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", size=24)
    barrier = threading.Barrier(4)

    def worker():
        barrier.wait()
        for _ in range(1000):
            font.getmetrics()
            font.getlength("Hello, world!")


    threads = [threading.Thread(target=worker) for _ in range(4)]
    for t in threads:
        t.start()
    for t in threads:
        t.join()
print("ok")

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions