[cairo] Multithreaded cairo-test

Chris Wilson chris at chris-wilson.co.uk
Fri Mar 23 15:58:19 PDT 2007


I wrote: 
> The first causality exposed by multi-threaded cairo-test is the
> _cairo_xlib_screen_list which lacked reference counting of the
> _cairo_xlib_screen_info_t.

Not only that but later, a recursive deadlock was exposed:

==25095== Deadlock[recursive] for mutex 0x409130C at:
==25095==    at 0x401F478: pthread_mutex_lock (ld_preload.c:51)
==25095==    by 0x4063ABE: _cairo_xlib_screen_info_destroy (cairo-xlib-screen.c:284)
==25095==    by 0x4062E7B: _cairo_xlib_surface_finish (cairo-xlib-surface.c:345)
==25095==    by 0x403E402: cairo_surface_finish (cairo-surface.c:471)
==25095==    by 0x403E4AF: cairo_surface_destroy (cairo-surface.c:396)
==25095==    by 0x4041C49: _cairo_pattern_release_surface (cairo-pattern.c:1630)
==25095==    by 0x4062144: _cairo_xlib_surface_composite (cairo-xlib-surface.c:1419)
==25095==    by 0x403D5FD: _cairo_surface_composite (cairo-surface.c:1092)
==25095==    by 0x403A8D4: _cairo_scaled_font_show_glyphs (cairo-scaled-font.c:1136)
==25095==    by 0x403F828: _cairo_surface_old_show_glyphs_draw_func (cairo-surface-fallback.c:901)
==25095==    by 0x403F2B2: _clip_and_composite (cairo-surface-fallback.c:391)
==25095==    by 0x403F6C5: _cairo_surface_fallback_show_glyphs (cairo-surface-fallback.c:952)
==25095==    by 0x403DE6D: _cairo_surface_show_glyphs (cairo-surface.c:1806)
==25095==    by 0x402FDAE: _cairo_gstate_show_glyphs (cairo-gstate.c:1595)
==25095==    by 0x4029AF0: cairo_show_text (cairo.c:2825)
==25095==    by 0x804A203: draw (glyph-cache-pressure.c:80)
==25095==    by 0x804B714: cairo_test_targets (cairo-test.c:293)
==25095==    by 0x426631A: start_thread (in /lib/tls/i686/cmov/libpthread-2.5.so)
==25095==    by 0x436F3ED: clone (in /lib/tls/i686/cmov/libc-2.5.so)
==25095== Mutex 0x409130C was taken by thread 9 at:
==25095==    at 0x401F4F2: pthread_mutex_lock (ld_preload.c:54)
==25095==    by 0x40639F1: _cairo_xlib_close_display (cairo-xlib-screen.c:300)
==25095==    by 0x418E995: XCloseDisplay (ClDisplay.c:71)
==25095==    by 0x804BE2B: cleanup_xlib (cairo-boilerplate.c:1038)
==25095==    by 0x804B23F: cairo_test_targets (cairo-test.c:355)
==25095==    by 0x426631A: start_thread (in /lib/tls/i686/cmov/libpthread-2.5.so)
==25095==    by 0x436F3ED: clone (in /lib/tls/i686/cmov/libc-2.5.so)
==25095== which waits on mutex 0x80F9CEC, taken by us, thread 10, at:
==25095==    at 0x401F4F2: pthread_mutex_lock (ld_preload.c:54)
==25095==    by 0x403DDD0: _cairo_surface_show_glyphs (cairo-surface.c:1796)
==25095==    by 0x402FDAE: _cairo_gstate_show_glyphs (cairo-gstate.c:1595)
==25095==    by 0x4029AF0: cairo_show_text (cairo.c:2825)
==25095==    by 0x804A203: draw (glyph-cache-pressure.c:80)
==25095==    by 0x804B714: cairo_test_targets (cairo-test.c:293)
==25095==    by 0x426631A: start_thread (in /lib/tls/i686/cmov/libpthread-2.5.so)
==25095==    by 0x436F3ED: clone (in /lib/tls/i686/cmov/libc-2.5.so)
--
Chris Wilson


-------------- next part --------------
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index 345cdbc..e96afab 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -314,9 +314,11 @@ _cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
 		cairo_xlib_hook_t *hook = info->close_display_hooks;
 		info->close_display_hooks = hook->next;
 
+		/* drop the list mutex for the callback */
+		CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
 		hook->func (info->display, hook->data);
-
 		free (hook);
+		CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
 	    }
 
 	    _cairo_xlib_screen_info_destroy_unlocked (info);
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index a85e700..401bafd 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2280,16 +2280,19 @@ _cairo_xlib_surface_remove_scaled_font (Display *dpy,
 	                               void    *data)
 {
     cairo_scaled_font_t *scaled_font = data;
-    cairo_xlib_surface_font_private_t	*font_private = scaled_font->surface_private;
+    cairo_xlib_surface_font_private_t	*font_private;
 
+    CAIRO_MUTEX_LOCK (scaled_font->mutex);
+    font_private = scaled_font->surface_private;
+    scaled_font->surface_private = NULL;
     _cairo_scaled_font_reset_cache (scaled_font);
+    CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
 
     /* separate function to avoid deadlock if we tried to remove the
      * close display hook ala _cairo_xlib_surface_scaled_font_fini() */
     if (font_private) {
 	XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset);
 	free (font_private);
-	scaled_font->surface_private = NULL;
     }
 }
 


More information about the cairo mailing list