[cairo] Multi-threading issue

Douwe Vos dmvos2000 at yahoo.com
Mon Oct 2 19:24:06 UTC 2017

So I was able to narrow down my crash Problem to the file cairo-ft-font.c. As far as I can see the lock_count on a cairo_ft_unscaled_font_t instance is protected by the mutex for that specific instance. At line 674 the lock_count is increased which is protected by the lock at line 673. When to many faces are open it tries to find faces where the lock_count is 0 at line 691 and then releases the face. Unfortunately this entry is not protected by the lock at line 673 (since this is another instance). So I added a lock on the returned entry at line 691 and recheck the value lock_count. Though this isn't optimal because there are now two locks, it did fix my crash problem. Below is the patch.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 3a4663d..8af6855 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -693,7 +693,12 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
            if (entry == NULL)
-           _font_map_release_face_lock_held (font_map, entry);
+           CAIRO_MUTEX_LOCK (entry->mutex);
+           if (_has_unlocked_face(entry))
+           {
+               _font_map_release_face_lock_held (font_map, entry);
+           }
+           CAIRO_MUTEX_UNLOCK (entry->mutex);
     _cairo_ft_unscaled_font_map_unlock ();

With regards,Douwe

    On Sunday, October 1, 2017, 12:16:47 AM GMT+2, Douwe Vos <dmvos2000 at yahoo.com> wrote:  
 Hi I'm programming a text-editor called Natpad. For calculating the document width/height in pixels I use multiple threads. The document is split in multiple blocks where each block is handled in a separate request. Each request (which handles a block of the document) is calculating block dimensions using a new PangoContext created by invoking gtk_widget_create_pango_context. Once in a while it causes a Segmentation Fault (it is pretty consistent when opening a specific file). I've tried to find the cause of the problem and looked into pangofc-shape.c. It does call pango_fc_font_lock_face but still ft_face->size appears to be NULL at line 325. I've tried to add a very simple lock around the whole _pango_fc_shape function but this merely serialized all requests. 
Any Ideas? Below is the stacktrace.

#0  0x00007ff4124d94b3 in _pango_fc_shape (font=0x7ff3c0199ae0, item_text=0x7ff3c030bea7 "͛,..)P.", item_length=2, analysis=0x7ff3d031ccd0, glyphs=0x27a5d40, 
    paragraph_text=0x7ff3c030be90 ".S.ԁ\036/.\001\026B.o.ý\362\262\254\250ěa͛,..)P.", paragraph_length=31) at /build/pango1.0-EzEh0I/pango1.0-1.38.1/./pango/pangofc-shape.c:325
#1  0x00007ff415749918 in pango_shape_full (item_text=0x7ff3c030bea7 "͛,..)P.", item_length=2, paragraph_text=<optimized out>, paragraph_length=31, analysis=0x7ff3d031ccd0, 
    glyphs=0x27a5d40) at /build/pango1.0-EzEh0I/pango1.0-1.38.1/./pango/shape.c:116
#2  0x00007ff41573b6d1 in shape_run (line=line at entry=0x7ff3c0312630, state=state at entry=0x7ff3f67fb840, item=item at entry=0x7ff3d031ccc0)
    at /build/pango1.0-EzEh0I/pango1.0-1.38.1/./pango/pango-layout.c:3296
#3  0x00007ff41573cf2c in process_item (layout=layout at entry=0x7ff3c8002210, line=line at entry=0x7ff3c0312630, state=state at entry=0x7ff3f67fb840, force_fit=force_fit at entry=1, 
    no_break_at_end=no_break_at_end at entry=0) at /build/pango1.0-EzEh0I/pango1.0-1.38.1/./pango/pango-layout.c:3409
#4  0x00007ff41573f4a4 in process_line (state=0x7ff3f67fb840, layout=0x7ff3c8002210) at /build/pango1.0-EzEh0I/pango1.0-1.38.1/./pango/pango-layout.c:3708
#5  pango_layout_check_lines (layout=<optimized out>) at /build/pango1.0-EzEh0I/pango1.0-1.38.1/./pango/pango-layout.c:4036
#6  0x00007ff4157411b8 in pango_layout_get_extents_internal (layout=0x7ff3c8002210, ink_rect=0x0, logical_rect=0x7ff3f67fba90, line_extents=0x0)
    at /build/pango1.0-EzEh0I/pango1.0-1.38.1/./pango/pango-layout.c:2590
#7  0x00007ff4157416b6 in pango_layout_get_pixel_extents (layout=0x7ff3c8002210, ink_rect=0x0, logical_rect=0x7ff3f67fba90)
    at /build/pango1.0-EzEh0I/pango1.0-1.38.1/./pango/pango-layout.c:2811
#8  0x00000000005930fa in cha_document_view_layout_page (document_view=0x28a5170, a_page=0x296aed0, page_layout_context=0x299dbf4, page_layout=0x29f8220, test_for_concurrent_update=1)
    at /home/superman/cpp-workspace/natpad/chameleon/src/layout/chadocumentview.c:701
#9  0x000000000059a20c in l_run_request (request=0x299dc40) at /home/superman/cpp-workspace/natpad/chameleon/src/layout/chapagelayoutrequest.c:199
#10 0x000000000063c498 in l_worker_run ()
#11 0x00007ff41496dbb5 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#12 0x00007ff413e466ba in start_thread (arg=0x7ff3f67fc700) at pthread_create.c:333
#13 0x00007ff413b7c3dd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

To further analyze the Problem I've started compiling all involved libraries from source. After compiling it from source (using an alternative build system) the problem seemed to have disappeared (which doesn't really helped me finding the cause). I have now installed a separate environment and will start building the libraries using the default built system from Linux Mint. Once I succeed I will try to find out where the size is set to NULL.

Douwe Vos
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.cairographics.org/archives/cairo/attachments/20171002/bc85f771/attachment.html>

More information about the cairo mailing list