[PATCH] [font-face] Close a race when resurrecting fonts.

Chris Wilson chris at chris-wilson.co.uk
Mon Jan 26 02:54:45 PST 2009


Paul Messmer provided a thorough analysis of a race between destroying the
final reference on a font and a concurrent recreation of the font -
demonstrating how it is possible for the create() to return the font that
was in the process of being freed.

To stop the race, we need to recheck the reference count upon taking the
mutex guarding the hash table.
---
 src/cairo-ft-font.c       |    6 ++++++
 src/cairo-toy-font-face.c |    6 ++++++
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 383b6e0..39cf164 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -513,6 +513,12 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font)
     /* All created objects must have been mapped in the font map. */
     assert (font_map != NULL);
 
+    if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled->base.ref_count)) {
+	/* somebody recreated the font whilst we waited for the lock */
+	_cairo_ft_unscaled_font_map_unlock ();
+	return;
+    }
+
     _cairo_hash_table_remove (font_map->hash_table,
 			      &unscaled->base.hash_entry);
 
diff --git a/src/cairo-toy-font-face.c b/src/cairo-toy-font-face.c
index 5a60b14..05ad495 100644
--- a/src/cairo-toy-font-face.c
+++ b/src/cairo-toy-font-face.c
@@ -358,6 +358,12 @@ _cairo_toy_font_face_destroy (void *abstract_face)
     /* All created objects must have been mapped in the hash table. */
     assert (hash_table != NULL);
 
+    if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->base.ref_count)) {
+	/* somebody recreated the font whilst we waited for the lock */
+	_cairo_toy_font_face_hash_table_unlock ();
+	return;
+    }
+
     if (font_face->base.hash_entry.hash != 0)
 	_cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
 
-- 
1.6.0.4


--=-bVgpndwyxQtJFPkIbhKa--



More information about the cairo mailing list