summaryrefslogtreecommitdiff
path: root/src/cairo-scaled-font.c
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2022-05-27 21:36:31 +0930
committerAdrian Johnson <ajohnson@redneon.com>2022-05-28 06:34:55 +0930
commita8c1858cf2bb6efb35c0678d135fd522ece9e2a4 (patch)
treee7b37d5013b2918dac57bb1bacbae00eb82655c4 /src/cairo-scaled-font.c
parent5dafd7411660f153219abceab64d5cc3be1c59a6 (diff)
downloadcairo-a8c1858cf2bb6efb35c0678d135fd522ece9e2a4.tar.gz
Fix deadlock in cairo-scaled-font.c
When cairo_scaled_glyph_page_cache needs to remove entries, cairo-cache calls _cairo_hash_table_random_entry() with the predicate _cairo_scaled_glyph_page_can_remove(). This function checks that the glyph_page scaled_font is not locked by testing scaled_font->cache_frozen. The scaled font is locked in the cache-cache destroy entry callback: _cairo_scaled_glyph_page_pluck(). There is a race condition here between testing scaled_font->cache_frozen and locking the font. Fix this by adding a new CAIRO_MUTEX_TRY_LOCK mutex operation, and using it to test and lock the scaled font in _cairo_scaled_glyph_page_can_remove(). Fixes the multithreaded case in #440
Diffstat (limited to 'src/cairo-scaled-font.c')
-rwxr-xr-xsrc/cairo-scaled-font.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 203b6a10c..4000a7082 100755
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -476,7 +476,7 @@ _cairo_scaled_glyph_page_pluck (void *closure)
scaled_font = page->scaled_font;
- CAIRO_MUTEX_LOCK (scaled_font->mutex);
+ /* The font is locked in _cairo_scaled_glyph_page_can_remove () */
_cairo_scaled_glyph_page_destroy (scaled_font, page);
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
}
@@ -2855,14 +2855,17 @@ _cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph,
scaled_glyph->has_info &= ~CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;
}
+/* _cairo_hash_table_random_entry () predicate. To avoid race conditions,
+ * the font is locked when tested. The font is unlocked in
+ * _cairo_scaled_glyph_page_pluck. */
static cairo_bool_t
_cairo_scaled_glyph_page_can_remove (const void *closure)
{
const cairo_scaled_glyph_page_t *page = closure;
- const cairo_scaled_font_t *scaled_font;
+ cairo_scaled_font_t *scaled_font;
scaled_font = page->scaled_font;
- return scaled_font->cache_frozen == 0;
+ return CAIRO_MUTEX_TRY_LOCK (scaled_font->mutex);
}
static cairo_status_t