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

Ryan Flannery ryan.flannery at gmail.com
Thu Nov 8 03:48:20 UTC 2018


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;
}


More information about the cairo mailing list