[cairo] [PATCH] Do not hold mutexes when calling destructors.

Jeff Muizelaar jeff at infidigm.net
Tue May 13 08:29:22 PDT 2008


On Tue, May 13, 2008 at 10:04:15AM -0400, Kristian Høgsberg wrote:
> On Fri, May 9, 2008 at 6:15 PM, Jeff Muizelaar <jeff at infidigm.net> wrote:
> > cairo_surface_destroy and _cairo_scaled_font_fini will call destroy closures
> >  which may call functions that attempt to acquire the mutex resulting in a
> >  deadlock. We fix this by releasing the lock for the call to
> >  cairo_surface_destroy or _cairo_scaled_font_fini.
> >  ---
> >
> >   src/cairo-pattern.c     |   17 ++++++++++++-----
> >   src/cairo-scaled-font.c |   14 +++++++++++---
> >   2 files changed, 23 insertions(+), 8 deletions(-)
> >
> >
> >  diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
> >  index 0f2eb3e..903d81f 100644
> >  --- a/src/cairo-pattern.c
> >  +++ b/src/cairo-pattern.c
> >  @@ -1515,13 +1515,20 @@ UNLOCK:
> >   static void
> >   _cairo_pattern_reset_solid_surface_cache (void)
> >   {
> >  -    int i;
> >  -
> >      CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
> >
> >  -    for (i = 0; i < solid_surface_cache.size; i++)
> >  -       cairo_surface_destroy (solid_surface_cache.cache[i].surface);
> >  -    solid_surface_cache.size = 0;
> >  +    /* remove surfaces starting from the end so that solid_surface_cache.cache
> >  +     * is always in a consistent state when we release the mutex. */
> >  +    while (solid_surface_cache.size) {
> >  +       cairo_surface_t *surface = solid_surface_cache.cache[solid_surface_cache.size-1].surface;
> >  +       solid_surface_cache.size--;
> >  +
> >  +       /* release the lock to avoid the possibility of a recursive
> >  +        * deadlock when the scaled font destroy closure gets called */
> >  +       CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
> >  +       cairo_surface_destroy (surface);
> >  +       CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
> >  +    }
> 
> Would it be better to say:
> 
>     struct solid_surface_cache copy;
> 
>     CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
>     copy = solid_surface_cache;
>     solid_surface_cache.size = 0;
>     CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
> 
>     for (i = 0; i < copy.size; i++)
>         cairo_surface_destroy (copy.cache[i].surface);

Perhaps. Is there an advantage to clearing the whole cache atomically?
If not, I don't really see what making a copy buys us.

-Jeff


More information about the cairo mailing list