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

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.
This commit is contained in:
Chris Wilson 2009-01-26 10:54:45 +00:00
parent 312b5680a5
commit 0f3e366f8b
2 changed files with 12 additions and 0 deletions

View file

@ -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);

View file

@ -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);