[cairo] memory problem with the X11 - SHM backend

Uli Schlachter psychon at znc.in
Sun Dec 1 03:11:20 PST 2013


Hi,

On 01.12.2013 11:30, Cedric Roux wrote:
> On 12/01/2013 10:55 AM, Uli Schlachter wrote:
>> On 01.12.2013 01:06, Cedric Roux wrote:
>>> I have a problem running you with X11/Xshm. This is a debian host here.
>>> The following program reports an always increasing "evs" thing.
>>>
>>> The first line it outputs is "1 evs" and the last one is
>>> "7409 evs".
>>
>> It doesn't do so here:
>>
>>   $ gcc t.c -lcairo -lX11&&  ./a.out | uniq -c
>>     7500 1 evs
> 
> I have 1.12.16 here, you are with the git one?

Does not happen with git nor with debian's 1.12.16-2.

> Still no problem if you do the following instead of the translate(0,0) ?
> 
>           static int z = 2;  cairo_matrix_init_translate(&m, z, z);
>           z = 2 - z;

Still no problem.

>> (Looks like the first paint() causes a SHM fallback and all the following
>> paint()s don't cause any Xlib calls, but just draw to the already existing SHM
>> image surface)
>>
>> If I do make the change mentioned below, I do get an increasing size of the
>> event queue. Why don't you run any event loop that gets events from Xlib?
> 
> There is the XCheckMaskEvent thing, but it never prints "events".
> even with XFlush before.
> 
> To figure things out (there are events in the queue, why doesn't
> XCheckMaskEvent return them?) I looked at the first_event field when
> calling XInitExtension and it is 65. I didn't check in the source of
> X11 but I suspect XCheckMaskEvent(-1L) won't look at this number
> because (1<<65) is out of range. Calling XNextEvent indeed removes the
> event from the queue.

XCheckMaskEvent() only handles core events. We are looking at an event coming
from the MIT-SHM extension. It gets generated via XSendEvent() by cairo:

http://cgit.freedesktop.org/cairo/tree/src/cairo-xlib-surface-shm.c?id=31eff5c6eb57ad379689748fd8c60a5ffe0ba481#n433

This is used to implement something like a "non-blocking XSync()". When Xlib
receives the event, LastKnownRequestProcessed(dpy) is updated and cairo can
re-use some shared memory that it was waiting for.

The idea for the main loop is to just discard this event, I guess. Chris would
know more.

> Well, I'm left with a problem here. I cannot use XNextEvent because
> my program uses select and XCheckMaskEvent leaves the event in
> the queue... So I guess I'll have to go with the XEventsQueued thing
> to check if there is something waiting and then use XNextEvent to
> really get it out. Or something...

You might be looking for something like this:

  while (XPending(dpy)) {
    XNextEvent(dpy, &ev);
    /* Handle the event */
  }

Cheers,
Uli

> Thanks for your help, Uli, and taking time to test things.
> I guess it was me misunderstanding something in there, probably
> the semantics of XCheckMaskEvent. Or something.
> 
> Regards.
> 
>>
>>> That means the X event queue is not emptied. (Please don't
>>> look at the style, it's a quick and dirty hack to let the problem pop
>>> up.)
>>>
>>> Oh yes, you need to create a 128x128 mini.png file to run it. Content
>>> does not seem to matter, I have a white image here.
>>>
>>> Am I doing something wrong with you or is the problem on your side?
>>
>> Uhm, so what exactly is the problem here? So far we are just at the symptom
>> "always increasing 'evs' thing". This might cause many actual problems, so which
>> one are you looking at?
>>
>>> If I call XSync(d, True) the queue is emptied and the original program
>>> that exhibited the problem and from which I wrote that little proof of
>>> concept still works pretty reasonably well. (What a terrific sentence
>>> I just wrote...)
>>> Except it smokes my CPU like hell, but that's none of your concern I
>>> suspect.
>>>
>>> In the hope that you can help me here...
>>> Regards cairo, have a nice sunday.
>>>
>>> #include<stdio.h>
>>> #include<cairo/cairo.h>
>>> #include<cairo/cairo-xlib.h>
>>> #include<X11/Xlib.h>
>>> #include<stdlib.h>
>>>
>>> int main(void)
>>> {
>>>     cairo_surface_t *image;
>>>     cairo_pattern_t *pletters;
>>>     cairo_surface_t *cs;
>>>     Display *d;
>>>     Pixmap p;
>>>
>>>     d = XOpenDisplay(0); if (!d) abort();
>>>     p = XCreatePixmap(d, DefaultRootWindow(d), 256, 256,
>>>                       DefaultDepth(d, DefaultScreen(d)));
>>>     cs = cairo_xlib_surface_create(d, p, DefaultVisual(d, DefaultScreen(d)),
>>>                                    256, 256);
>>>
>>>     //image = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 512, 512);
>>>     image = cairo_image_surface_create_from_png("mini.png");
>>>     pletters = cairo_pattern_create_for_surface(image);
>>>
>>>     int y;
>>>     for (y=0; y<  500; y++) {
>>>       int i;
>>>       cairo_matrix_t m;
>>>       cairo_t *c = cairo_create(cs);
>>>
>>>       //cairo_scale(c, 0.5, 0.5);
>>>       //cairo_translate(c, 1, 1);
>>>       for (i = 0; i<  15; i++) {
>>>         //static int z = 2;  cairo_matrix_init_translate(&m, 0, 0); //z =
>>> 2 - z;
>>>         cairo_matrix_init_translate(&m, 0, 0); //z = 2 - z;
>>>         cairo_pattern_set_matrix(pletters,&m);
>>>         cairo_set_source(c, pletters);
>>>         cairo_paint(c);
>>>
>>>         //XSync(d, True);
>>>         printf("%d evs\n", XEventsQueued(d, QueuedAfterReading));
>>>         //XFlush(d);
>>>
>>>         XEvent ev; while (XCheckMaskEvent(d, -1L,&ev)) {
>>> printf("event!\n"); }
>>
>> Add here: cairo_surface_flush(cs); and the event queue gets filled with
>> MIT-SHM-Completion events (and the program of course runs a lot slower).
>>
>>>       }
>>>
>>>       cairo_destroy(c);
>>>     }
>>>
>>>     return 0;
>>> }
>>>
>>
>> Cheers,
>> Uli
> 


-- 
No matter how much cats fight, there always seem to be plenty of kittens.


More information about the cairo mailing list