[Xcb] [Socket handoff] Waiting forever...

Clemens Eisserer linuxhippy at gmail.com
Wed Jul 1 08:52:21 PDT 2009


Hi Jamey,

Thanks a lot for looking at that stuff :)

> The simplest approach you can take here is to issue a GetInputFocus
> request immediately after xcb_take_socket, and then do it again every
> 64k requests that you issue. You *don't* need to wait for the reply
> immediately; just make sure you pick up the reply eventually, or there
> will be a memory leak. This is not optimal, but it is at least correct
> and simple.

Thanks for the very detailed explanation, and for the howto to work
arround that problem.
Sorry for the dumb question, when I issue a getInputFocus request with
self-generated protocol, how can I consume the reply in native code?
The rest of the application is using the xlib-api, so probably I am
not able to use xcb's api?
Just for a test I modified the java code to send a GetInputFocus
request every 10 requests, and the blocking seems to be gone but as
expected the app now leaks memory.

To have a simple playground I also modified my c-testcase, but now it
aborts either with:
> handoff: xcb_io.c:242: process_responses: Assertion `(((long) (dpy->last_request_read) - (long) (dpy->request)) <=
> 0)' failed.

or the XServer resets the connection:
> XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server "localhost:0.0"
>      after 130277 requests (65146 known processed) with 1 events remaining.

However using wireshark the protocol I generated at least *seemed*
valid (wireshark was able to decode it ;) ).

> I wonder if your output queue is *too* big? If you flush more often, the
> X server can get started on the work you're requesting sooner. The only
> reason to have an output queue at all is because system calls are
> expensive and you want to do fewer of them.
>
> If that doesn't help, something like `strace -T` may tell you what
> syscalls are keeping your process waiting.
Thanks again :)

Last question, why does XEventsQueued cause a socket-takeback of the
native side?
The application I use frequently calls XEventQueued, and it seems like
socket-handoff ping-pong is taking place :-/
Any idea howto work arround that issue?

Thanks again, Clemens
-------------- next part --------------
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/render.h>
#include <stdlib.h>
#include <math.h>
#include <stdlib.h>
#include <sys/time.h>

#include <xcb/xcb.h>
#include <X11/Xlib-xcb.h>

#include <sys/uio.h>

Display *display;
int screen;
Window root, window;
XEvent event;

int RENDER;


int fillRect(Picture dst, char* data) {
        unsigned int* req_i = (unsigned int*) data;
        unsigned short* req_s = (unsigned short*) data;
        unsigned char* req_b = (unsigned char*) data;
        
	/*Compiler's nightmare ;) */
        req_b[0] = RENDER;
        req_b[1] = 26; //FillRectangles-Opcode
        req_s[1] = 9;  //Request-length

        req_b[4] = 3; //Over
        
        req_i[2] = dst; 

        req_s[6] = 0xffff; //green
        req_s[7] = 0xffff; //Red
        req_s[8] = 0;      //Blue
        req_s[9] = 0xffff; //A

        req_s[10] = 100;
        req_s[11] = 100;
        req_s[12] = 20;
        req_s[13] = 20;

        req_s[14] = 120;
        req_s[15] = 120;
        req_s[16] = 10;
        req_s[17] = 10;

        return 36;
}

int getInputFocus(char* data) {
        unsigned short* req_s = (unsigned short*) data;
        unsigned char* req_b = (unsigned char*) data;
        
        req_b[0] = 43;
        req_b[1] = 0;
        req_s[1] = 1;  //Request-length
	
	return 4;
}

static void return_socket(void *closure)
{ }


void testLoop(xcb_connection_t *con, char* buffer, Picture picture) 
{
  XRenderColor color_white = {.red=0xffff, .green=0xffff, .blue=0xffff, .alpha=0xffff};

  int z;  //The higher the iteration count, the sooner (more likely?) it happens
  for(z=0; z < 1000; z++)  {

       /*Use a C based function*/ 
       XRenderFillRectangle(display, PictOpOver, picture, &color_white, 0, 0, 1, 1);
       
       /*Grab the socket*/
       int flags = 0;
       uint64_t sent;
       int ret = xcb_take_socket(con, &return_socket, &flags, 0, &sent);
       
       /*Produce self-generated protocol*/
       int requests = 0;
       int written = 0;
       for(requests = 0; requests < 500; requests++) {  //770 self-generated requests cause xcb to hang, 769 work perfectly.
         written += fillRect(picture, &buffer[written]);
	 written += getInputFocus(&buffer[written]);
       }

       /*Write self-generated protocol*/
       struct iovec vect;
       vect.iov_base = buffer;
       vect.iov_len = written;
       xcb_writev(con, &vect, 1, requests);
  }
}

int main(int argc, char *argv[])
{
        /*Bosing initialization stuff*/
	display=XOpenDisplay(NULL);
	
	int render_event_base, render_error_base;
	int render_present=XRenderQueryExtension(display, &render_event_base, &render_error_base);
	if (!render_present) {
		fprintf(stderr, "RENDER extension missing!\n");
		abort();
	}
	
	XRenderPictFormat *fmt=XRenderFindStandardFormat(display, PictStandardRGB24);
	screen=DefaultScreen(display);
	root=DefaultRootWindow(display);
	
	window = XCreateWindow(display, root, 0, 0, 640, 480, 0,
		DefaultDepth(display, screen), InputOutput,
		DefaultVisual(display, screen), 
		0, NULL);
	XRenderPictureAttributes pict_attr;
	
	pict_attr.poly_edge=PolyEdgeSmooth;
	pict_attr.poly_mode=PolyModeImprecise;
	Picture picture=XRenderCreatePicture(display, window, fmt, CPPolyEdge|CPPolyMode, &pict_attr);
	
	XSelectInput(display, window, KeyPressMask|KeyReleaseMask|ExposureMask
		|ButtonPressMask|StructureNotifyMask);
	
	
	/* now make the window visible */
	XMapWindow(display, window);
	

       /*Fetch the RENDER extension's opcode*/
       char renderName[] = RENDER_NAME;
       int x;
       XQueryExtension(display, renderName , &RENDER, &x, &x);

       xcb_connection_t* con = XGetXCBConnection(display);

       char* buffer = (char*) malloc(5000000);

	while(1) {
		XNextEvent(display, &event);
		
		switch(event.type) {
			case Expose:
{
                          testLoop(con, buffer, picture);

				break;
			case DestroyNotify:
				return 0;
		}
	}
	
}
	return 0;
}


More information about the Xcb mailing list