Ryan Flannery
2018-11-08 03:48:20 UTC
Hi,
I'm running into a segfault with cairo_xcb_surface_create() in an
application I'm working on. My application can (now) create an X
display (using cairo and other APIs), do some work, then destroy that
UI, and then possibly create another. Whenever I try to create a
second display, I get a crash in cairo_xcb_surface_create() reliably.
I have sample code below that I've stripped-down and reproduces the
segfault reliably on OpenBSD current (and the recent 6.4 release), as
well as a recent-ish release of Arch linux, all with latest versions
of cairo and X libs.
I'm guessing I'm either missing some tear-down/cleanup between calls
that I'm not seeing from the documentation and google'ing, or there's
some state/etc within the cairo API I'm missing.
Anyone seen something similar or have any idea why this might be caused?
Sample code below. The "test()" function is where I create an x window
(and related bits), followed by a cairo surface and cairo_t, and then
simply sleep for a second and tear everything down. The second call to
test() will reliably segfault on cairo_xcb_surface_create().
Cheers,
-Ryan
/*
* Test demonstrating how a second call to cairo_xcb_surface_create() bombs.
* Note I've stripped down most of the setup/etc to be as minimal as possible.
* Error checking on all xcb/cairo calls previous show no errors when present.
*/
#include <stdio.h>
#include <unistd.h>
#include <xcb/xcb.h>
#include <cairo/cairo-xcb.h>
xcb_visualtype_t*
get_root_visual(xcb_screen_t *screen)
{
xcb_depth_iterator_t i = xcb_screen_allowed_depths_iterator(screen);
for (; i.rem; xcb_depth_next(&i)) {
if (i.data->depth != 32)
continue;
xcb_visualtype_iterator_t vi;
vi = xcb_depth_visuals_iterator(i.data);
for (; vi.rem; xcb_visualtype_next(&vi)) {
return vi.data;
}
}
return NULL;
}
void
test()
{
xcb_connection_t *x = xcb_connect(NULL, NULL);
xcb_drawable_t w = xcb_generate_id(x);
xcb_screen_t *s = xcb_setup_roots_iterator(xcb_get_setup(x)).data;
xcb_visualtype_t *v = get_root_visual(s);
xcb_create_window(
x,
32, /* force 32 bit */
w,
s->root,
0, 0, 0, 0, /* x,y,w,h */
0, /* border width */
XCB_WINDOW_CLASS_INPUT_OUTPUT,
s->root_visual,
0, NULL);
cairo_surface_t *cs = cairo_xcb_surface_create(
x,
w,
v,
1000,
1000);
cairo_t *c = cairo_create(cs);
sleep(1);
cairo_destroy(c);
cairo_surface_destroy(cs);
xcb_destroy_window(x, w);
xcb_disconnect(x);
}
int
main()
{
printf("first call...\n");
test();
printf("second call...\n");
test(); /* segfaults on cairo_xcb_surface_create() */
return 0;
}
I'm running into a segfault with cairo_xcb_surface_create() in an
application I'm working on. My application can (now) create an X
display (using cairo and other APIs), do some work, then destroy that
UI, and then possibly create another. Whenever I try to create a
second display, I get a crash in cairo_xcb_surface_create() reliably.
I have sample code below that I've stripped-down and reproduces the
segfault reliably on OpenBSD current (and the recent 6.4 release), as
well as a recent-ish release of Arch linux, all with latest versions
of cairo and X libs.
I'm guessing I'm either missing some tear-down/cleanup between calls
that I'm not seeing from the documentation and google'ing, or there's
some state/etc within the cairo API I'm missing.
Anyone seen something similar or have any idea why this might be caused?
Sample code below. The "test()" function is where I create an x window
(and related bits), followed by a cairo surface and cairo_t, and then
simply sleep for a second and tear everything down. The second call to
test() will reliably segfault on cairo_xcb_surface_create().
Cheers,
-Ryan
/*
* Test demonstrating how a second call to cairo_xcb_surface_create() bombs.
* Note I've stripped down most of the setup/etc to be as minimal as possible.
* Error checking on all xcb/cairo calls previous show no errors when present.
*/
#include <stdio.h>
#include <unistd.h>
#include <xcb/xcb.h>
#include <cairo/cairo-xcb.h>
xcb_visualtype_t*
get_root_visual(xcb_screen_t *screen)
{
xcb_depth_iterator_t i = xcb_screen_allowed_depths_iterator(screen);
for (; i.rem; xcb_depth_next(&i)) {
if (i.data->depth != 32)
continue;
xcb_visualtype_iterator_t vi;
vi = xcb_depth_visuals_iterator(i.data);
for (; vi.rem; xcb_visualtype_next(&vi)) {
return vi.data;
}
}
return NULL;
}
void
test()
{
xcb_connection_t *x = xcb_connect(NULL, NULL);
xcb_drawable_t w = xcb_generate_id(x);
xcb_screen_t *s = xcb_setup_roots_iterator(xcb_get_setup(x)).data;
xcb_visualtype_t *v = get_root_visual(s);
xcb_create_window(
x,
32, /* force 32 bit */
w,
s->root,
0, 0, 0, 0, /* x,y,w,h */
0, /* border width */
XCB_WINDOW_CLASS_INPUT_OUTPUT,
s->root_visual,
0, NULL);
cairo_surface_t *cs = cairo_xcb_surface_create(
x,
w,
v,
1000,
1000);
cairo_t *c = cairo_create(cs);
sleep(1);
cairo_destroy(c);
cairo_surface_destroy(cs);
xcb_destroy_window(x, w);
xcb_disconnect(x);
}
int
main()
{
printf("first call...\n");
test();
printf("second call...\n");
test(); /* segfaults on cairo_xcb_surface_create() */
return 0;
}
--
cairo mailing list
***@cairographics.org
https://lists.cairographic
cairo mailing list
***@cairographics.org
https://lists.cairographic