[cairo] cairo_xcb_surface_create() segfaults on second call with different xcb info

Ryan Flannery ryan.flannery at gmail.com
Wed Nov 14 01:26:58 UTC 2018


On Sat, Nov 10, 2018 at 4:11 AM Uli Schlachter <psychon at znc.in> wrote:
>
> On 10.11.18 06:36, Ryan Flannery wrote:
> [...]
> >> Also: Finishing the device automatically finishes all cairo_surface_t
> >> instances for this XCB devices.
> >
> > Ok - this raises a question for me about the device state between
> > surface creation.
> > Do you mean one of the following:
> >
> > 1. Calling cairo_device_finish(cairo_surface_get_device(cs)) when
> > destroying a xcb/cairo setup should, effectively, remove the state
> > tracked in cairo_xcb_surface_create() (and thus allow a subsequent
> > call with the same pointer value, but different contents, succeed)?
> >
> > -or-
> >
> > 2. That there's still state there and I should track that
> > cairo_device_t* reference on my side, even if I call the
> > cairo_device_finish() bits?
>
> I think I mean (1). Finishing the cairo_device_t instance tries to get
> rid of everything that uses the underlying xcb_connection_t*. It does
> not do this completely, but the difference should not matter to you.
>
> The reason is reference counting: Finishing the cairo_device_t finishes
> everything using this cairo_device_t / xcb_connection_t. "Finishes" here
> means "makes unusable". However, it does not actually free everything,
> since other pieces of code could still have a reference that keeps the
> cairo_device_t alive (e.g. through cairo_device_reference,
> cairo_surface_reference, or just cairo_xcb_surface_create). All this
> "state" is cannot be freed yet, because otherwise the code having that
> reference would end up with a dangling pointer. But, any attempt of
> using one of these objects generates a CAIRO_STATUS_SURFACE_FINISHED or
> CAIRO_STATUS_DEVICE_FINISHED error status.
>
> The important bit for you is that finishing the connection removes the
> cairo_device_t from cairo's internal cache, so any following attempts at
> using the same xcb_connection_t will create a new cairo_device_t instance.
>

That worked! Calling
        cairo_device_finish(cairo_surface_get_device(cs));
before calling cairo_surface_destroy(cs) reliably solves the problem.

And following the code you referenced I can see (1) why the segfault
was happening in the first place and (2) how this resolves it.

Many thanks again Uli!

Cheers,
-Ryan


More information about the cairo mailing list