[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