Re: cairo_xcb_surface_create() segfaults on second call with different xcb info
Uli Schlachter <[email protected]> Sat, 10 Nov 2018 10:11:36 +0100
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[email protected]> |
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. > I could probably answer that on my own if I had my dev laptop with me, If you want to dig into some code: src/cairo-xcb-connection.c has a _cairo_xcb_device_backend struct that defines the operations on a cairo_xcb_connection_t (which is basically a non-public subtype of cairo_device_t). _cairo_xcb_connection_get() is used to "turn" a xcb_connection_t into a cairo_xcb_connection_t. This first checks a global list called "connections" for a matching entry and otherwise creates a new instance of a cairo_xcb_connection_t. _device_finish() does the work in cairo_device_finish(). It gets rid of open fonts and a cairo-specific representation of an X11 screen (which contains a list of all cairo-xcb surfaces using this one screen; thus this also cairo_surface_finish()es all surfaces using this device). Later, _device_destroy() is run when the reference count of the cairo_device_t actually drops to zero. This does not do anything with the xcb_connection_t, but instead does all the freeing that is necessary. E.g., some internal mutexes are destroyed. This also free()s the cairo_xcb_connection_t itself. Hope this helps, Uli -- "Why make things difficult, when it is possible to make them cryptic and totally illogical, with just a little bit more effort?" -- A. P. J. -- cairo mailing list [email protected] https://lists.cairographics.org/mailman/listinfo/cairo