Re: memory problem with the X11 - SHM backend

Uli Schlachter <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <[email protected]>
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.
-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.