Skip to content

Commit e4d72b5

Browse files
colesburyhugovk
authored andcommitted
Use critical sections to protect FontObject
FreeType FT_Face objects are not thread-safe. Use per-object critical sections to protect FontObject methods that access the underlying FT_Face in the free-threaded build. Fixes #9497
1 parent 8e9068e commit e4d72b5

1 file changed

Lines changed: 100 additions & 10 deletions

File tree

src/_imagingft.c

Lines changed: 100 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ text_layout(
518518
}
519519

520520
static PyObject *
521-
font_getlength(FontObject *self, PyObject *args) {
521+
font_getlength_impl(FontObject *self, PyObject *args) {
522522
int length; /* length along primary axis, in 26.6 precision */
523523
GlyphInfo *glyph_info = NULL; /* computed text layout */
524524
size_t i, count; /* glyph_info index and length */
@@ -567,6 +567,15 @@ font_getlength(FontObject *self, PyObject *args) {
567567
return PyLong_FromLong(length);
568568
}
569569

570+
static PyObject *
571+
font_getlength(FontObject *self, PyObject *args) {
572+
PyObject *result;
573+
Py_BEGIN_CRITICAL_SECTION(self);
574+
result = font_getlength_impl(self, args);
575+
Py_END_CRITICAL_SECTION();
576+
return result;
577+
}
578+
570579
static int
571580
bounding_box_and_anchors(
572581
FT_Face face,
@@ -746,7 +755,7 @@ bounding_box_and_anchors(
746755
}
747756

748757
static PyObject *
749-
font_getsize(FontObject *self, PyObject *args) {
758+
font_getsize_impl(FontObject *self, PyObject *args) {
750759
int width, height, x_offset, y_offset;
751760
int load_flags; /* FreeType load_flags parameter */
752761
int error;
@@ -820,7 +829,16 @@ font_getsize(FontObject *self, PyObject *args) {
820829
}
821830

822831
static PyObject *
823-
font_render(FontObject *self, PyObject *args) {
832+
font_getsize(FontObject *self, PyObject *args) {
833+
PyObject *result;
834+
Py_BEGIN_CRITICAL_SECTION(self);
835+
result = font_getsize_impl(self, args);
836+
Py_END_CRITICAL_SECTION();
837+
return result;
838+
}
839+
840+
static PyObject *
841+
font_render_impl(FontObject *self, PyObject *args) {
824842
int x, y; /* pen position, in 26.6 precision */
825843
int px, py; /* position of current glyph, in pixels */
826844
int x_min, y_max; /* text offset in 26.6 precision */
@@ -1233,6 +1251,15 @@ font_render(FontObject *self, PyObject *args) {
12331251
return NULL;
12341252
}
12351253

1254+
static PyObject *
1255+
font_render(FontObject *self, PyObject *args) {
1256+
PyObject *result;
1257+
Py_BEGIN_CRITICAL_SECTION(self);
1258+
result = font_render_impl(self, args);
1259+
Py_END_CRITICAL_SECTION();
1260+
return result;
1261+
}
1262+
12361263
static PyObject *
12371264
font_getvarnames(FontObject *self) {
12381265
int error;
@@ -1372,7 +1399,7 @@ font_getvaraxes(FontObject *self) {
13721399
}
13731400

13741401
static PyObject *
1375-
font_setvarname(FontObject *self, PyObject *args) {
1402+
font_setvarname_impl(FontObject *self, PyObject *args) {
13761403
int error;
13771404

13781405
int instance_index;
@@ -1389,7 +1416,16 @@ font_setvarname(FontObject *self, PyObject *args) {
13891416
}
13901417

13911418
static PyObject *
1392-
font_setvaraxes(FontObject *self, PyObject *args) {
1419+
font_setvarname(FontObject *self, PyObject *args) {
1420+
PyObject *result;
1421+
Py_BEGIN_CRITICAL_SECTION(self);
1422+
result = font_setvarname_impl(self, args);
1423+
Py_END_CRITICAL_SECTION();
1424+
return result;
1425+
}
1426+
1427+
static PyObject *
1428+
font_setvaraxes_impl(FontObject *self, PyObject *args) {
13931429
int error;
13941430

13951431
PyObject *axes, *item;
@@ -1442,6 +1478,15 @@ font_setvaraxes(FontObject *self, PyObject *args) {
14421478
Py_RETURN_NONE;
14431479
}
14441480

1481+
static PyObject *
1482+
font_setvaraxes(FontObject *self, PyObject *args) {
1483+
PyObject *result;
1484+
Py_BEGIN_CRITICAL_SECTION(self);
1485+
result = font_setvaraxes_impl(self, args);
1486+
Py_END_CRITICAL_SECTION();
1487+
return result;
1488+
}
1489+
14451490
static void
14461491
font_dealloc(FontObject *self) {
14471492
if (self->face) {
@@ -1483,30 +1528,75 @@ font_getattr_style(FontObject *self, void *closure) {
14831528
}
14841529

14851530
static PyObject *
1486-
font_getattr_ascent(FontObject *self, void *closure) {
1531+
font_getattr_ascent_impl(FontObject *self, void *closure) {
14871532
return PyLong_FromLong(PIXEL(self->face->size->metrics.ascender));
14881533
}
14891534

14901535
static PyObject *
1491-
font_getattr_descent(FontObject *self, void *closure) {
1536+
font_getattr_ascent(FontObject *self, void *closure) {
1537+
PyObject *result;
1538+
Py_BEGIN_CRITICAL_SECTION(self);
1539+
result = font_getattr_ascent_impl(self, closure);
1540+
Py_END_CRITICAL_SECTION();
1541+
return result;
1542+
}
1543+
1544+
static PyObject *
1545+
font_getattr_descent_impl(FontObject *self, void *closure) {
14921546
return PyLong_FromLong(-PIXEL(self->face->size->metrics.descender));
14931547
}
14941548

14951549
static PyObject *
1496-
font_getattr_height(FontObject *self, void *closure) {
1550+
font_getattr_descent(FontObject *self, void *closure) {
1551+
PyObject *result;
1552+
Py_BEGIN_CRITICAL_SECTION(self);
1553+
result = font_getattr_descent_impl(self, closure);
1554+
Py_END_CRITICAL_SECTION();
1555+
return result;
1556+
}
1557+
1558+
static PyObject *
1559+
font_getattr_height_impl(FontObject *self, void *closure) {
14971560
return PyLong_FromLong(PIXEL(self->face->size->metrics.height));
14981561
}
14991562

15001563
static PyObject *
1501-
font_getattr_x_ppem(FontObject *self, void *closure) {
1564+
font_getattr_height(FontObject *self, void *closure) {
1565+
PyObject *result;
1566+
Py_BEGIN_CRITICAL_SECTION(self);
1567+
result = font_getattr_height_impl(self, closure);
1568+
Py_END_CRITICAL_SECTION();
1569+
return result;
1570+
}
1571+
1572+
static PyObject *
1573+
font_getattr_x_ppem_impl(FontObject *self, void *closure) {
15021574
return PyLong_FromLong(self->face->size->metrics.x_ppem);
15031575
}
15041576

15051577
static PyObject *
1506-
font_getattr_y_ppem(FontObject *self, void *closure) {
1578+
font_getattr_x_ppem(FontObject *self, void *closure) {
1579+
PyObject *result;
1580+
Py_BEGIN_CRITICAL_SECTION(self);
1581+
result = font_getattr_x_ppem_impl(self, closure);
1582+
Py_END_CRITICAL_SECTION();
1583+
return result;
1584+
}
1585+
1586+
static PyObject *
1587+
font_getattr_y_ppem_impl(FontObject *self, void *closure) {
15071588
return PyLong_FromLong(self->face->size->metrics.y_ppem);
15081589
}
15091590

1591+
static PyObject *
1592+
font_getattr_y_ppem(FontObject *self, void *closure) {
1593+
PyObject *result;
1594+
Py_BEGIN_CRITICAL_SECTION(self);
1595+
result = font_getattr_y_ppem_impl(self, closure);
1596+
Py_END_CRITICAL_SECTION();
1597+
return result;
1598+
}
1599+
15101600
static PyObject *
15111601
font_getattr_glyphs(FontObject *self, void *closure) {
15121602
return PyLong_FromLong(self->face->num_glyphs);

0 commit comments

Comments
 (0)