Bug 57094

Summary: X11 fonts may be cleaned by unrelated thread
Product: cairo Reporter: Benjamin Berg <benjamin>
Component: generalAssignee: Chris Wilson <chris>
Status: RESOLVED MOVED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: normal    
Priority: medium CC: freedesktop
Version: 1.12.8   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:
Bug Depends on:    
Bug Blocks: 68382    

Description Benjamin Berg 2012-11-13 20:15:35 UTC
cairo_scaled_font_destroy may destroy fonts that have been created on a different backend. I am hitting a deadlock in one of my programs because of this. What happens is that GDK is doing some X calls (eg. XSync) while a second thread is rendering a PDF. The PDF rendering causes cairo_scaled_font_destroy, which in turn calls XRenderFreeGlyphSet.

From IRC:
< psychon> ickle: ^ (I guess that cairo is supposed to only call into Xlib from threads that use cairo-xlib, so this XFreeGlyphSet is wrong)
< ickle> restore the taskqueue


This is the backtrace of the X call that should not happen:
(gdb) bt
#0  _XGetRequest (dpy=0xdac8e0, type=19 '\023', len=8) at ../../src/XlibInt.c:1967
#1  0x00007fffeffd3f00 in XRenderFreeGlyphSet () from /usr/lib/x86_64-linux-gnu/libXrender.so.1
#2  0x00007ffff23094b6 in _cairo_xlib_font_fini (abstract_private=0x1316820, font=<optimized out>)
    at /var/tmp/cairo-1.12.3~fsetec.2/src/cairo-xlib-render-compositor.c:718
#3  0x00007ffff22daae1 in _cairo_scaled_font_fini_internal (scaled_font=0x1318a80) at /var/tmp/cairo-1.12.3~fsetec.2/src/cairo-scaled-font.c:864
#4  0x00007ffff22db13d in cairo_scaled_font_destroy (scaled_font=<optimized out>) at /var/tmp/cairo-1.12.3~fsetec.2/src/cairo-scaled-font.c:1337
#5  INT_cairo_scaled_font_destroy (scaled_font=<optimized out>) at /var/tmp/cairo-1.12.3~fsetec.2/src/cairo-scaled-font.c:1273
#6  0x00007ffff22a8d79 in _cairo_gstate_unset_scaled_font (gstate=<error reading variable: Unhandled dwarf expression opcode 0xfa>, 
    gstate=<error reading variable: Unhandled dwarf expression opcode 0xfa>) at /var/tmp/cairo-1.12.3~fsetec.2/src/cairo-gstate.c:1632
#7  0x00007ffff22ac897 in _cairo_gstate_set_font_face (gstate=0x1347630, font_face=0xde1ac0) at /var/tmp/cairo-1.12.3~fsetec.2/src/cairo-gstate.c:1873
#8  0x00007ffff229f565 in cairo_set_font_face (cr=0x11bd360, font_face=<optimized out>) at /var/tmp/cairo-1.12.3~fsetec.2/src/cairo.c:2790
#9  0x00007fffe52ca39c in CairoOutputDev::updateFont(GfxState*) () from /usr/lib/x86_64-linux-gnu/libpoppler-glib.so.8
#10 0x00007fffe4f4883d in Gfx::opShowSpaceText(Object*, int) () from /usr/lib/x86_64-linux-gnu/libpoppler.so.28
#11 0x00007fffe4f411b4 in Gfx::go(bool) () from /usr/lib/x86_64-linux-gnu/libpoppler.so.28
#12 0x00007fffe4f41620 in Gfx::display(Object*, bool) () from /usr/lib/x86_64-linux-gnu/libpoppler.so.28
#13 0x00007fffe4f81d94 in Page::displaySlice(OutputDev*, double, double, int, bool, bool, int, int, int, int, bool, bool (*)(void*), void*, bool (*)(Annot*, void*), void*) () from /usr/lib/x86_64-linux-gnu/libpoppler.so.28
#14 0x00007fffe52c0f69 in ?? () from /usr/lib/x86_64-linux-gnu/libpoppler-glib.so.8
#15 0x00007ffff4eff7bc in ffi_call_unix64 () from /usr/lib/x86_64-linux-gnu/libffi.so.5

----

For people interested (not really that important), this is how it hangs later on. XCB is waiting for a too high sequence number, because the above call was counted internally, but not send to the X server.
(gdb) bt
#0  0x00007ffff6e46e73 in *__GI___poll (fds=<optimized out>, fds@entry=0x7fffffffcc90, nfds=<optimized out>, nfds@entry=1, timeout=timeout@entry=-1)
    at ../sysdeps/unix/sysv/linux/poll.c:87
#1  0x00007ffff7bc8212 in _xcb_conn_wait (c=c@entry=0xdb0a10, cond=cond@entry=0x7fffffffcd00, vector=vector@entry=0x0, count=count@entry=0x0)
    at ../../src/xcb_conn.c:400
#2  0x00007ffff7bc9747 in wait_for_reply (c=c@entry=0xdb0a10, request=21351, e=e@entry=0x7fffffffcdc8) at ../../src/xcb_in.c:390
#3  0x00007ffff7bc996b in xcb_wait_for_reply (c=0xdb0a10, request=21351, e=0x7fffffffcdc8) at ../../src/xcb_in.c:420
#4  0x00007ffff2fdf32d in _XReply (dpy=0xdac8e0, rep=0x7fffffffce20, extra=6, discard=0) at ../../src/xcb_io.c:601
#5  0x00007ffff2d9701a in XIQueryPointer () from /usr/lib/x86_64-linux-gnu/libXi.so.6
Comment 1 Benjamin Berg 2013-04-30 22:18:45 UTC
Well, I finally decided to work around this issue by forking. So the PDF is now rendered in a separate process instead of only a separate thread. Passing image surfaces through FDs isn't hard.

Works nice for me.
Comment 2 Behdad Esfahbod 2013-05-01 20:57:19 UTC
(In reply to comment #0)
> cairo_scaled_font_destroy may destroy fonts that have been created on a
> different backend. I am hitting a deadlock in one of my programs because of
> this. What happens is that GDK is doing some X calls (eg. XSync) while a
> second thread is rendering a PDF. The PDF rendering causes
> cairo_scaled_font_destroy, which in turn calls XRenderFreeGlyphSet.
> 
> From IRC:
> < psychon> ickle: ^ (I guess that cairo is supposed to only call into Xlib
> from threads that use cairo-xlib, so this XFreeGlyphSet is wrong)
> < ickle> restore the taskqueue

I see no trace of the task queue left in the code base.  :(
Comment 3 Benjamin Berg 2014-02-24 11:01:50 UTC
Hey, any news on this? This seems like a rather nasty issue, if cairo is supposed to be thread safe.
Comment 4 GitLab Migration User 2018-08-25 13:51:20 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/cairo/cairo/issues/233.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.