X-Git-Url: http://git.demorecorder.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fxcb_out.c;h=1b68215a8c3d20d64fddba17bb19c6bdd8fcf2bd;hb=2c8b5994b3fbba343199ef555594a32e29d8bcee;hp=eb41e592089312110e1e43694de6f8f7551ee326;hpb=d69c403cba9bdebd1bd41b62ae7e28f5852248d4;p=free-sw%2Fxcb%2Flibxcb diff --git a/src/xcb_out.c b/src/xcb_out.c index eb41e59..1b68215 100644 --- a/src/xcb_out.c +++ b/src/xcb_out.c @@ -59,6 +59,8 @@ static int write_block(XCBConnection *c, struct iovec *vector, int count) CARD32 XCBGetMaximumRequestLength(XCBConnection *c) { + if(c->has_error) + return 0; pthread_mutex_lock(&c->out.reqlenlock); if(!c->out.maximum_request_length) { @@ -91,6 +93,9 @@ unsigned int XCBSendRequest(XCBConnection *c, int flags, struct iovec *vector, c int veclen = req->count; enum workarounds workaround = WORKAROUND_NONE; + if(c->has_error) + return 0; + assert(c != 0); assert(vector != 0); assert(req->count > 0); @@ -107,7 +112,10 @@ unsigned int XCBSendRequest(XCBConnection *c, int flags, struct iovec *vector, c { const XCBQueryExtensionRep *extension = XCBGetExtensionData(c, req->ext); if(!(extension && extension->present)) + { + _xcb_conn_shutdown(c); return 0; + } ((CARD8 *) vector[0].iov_base)[0] = extension->major_opcode; ((CARD8 *) vector[0].iov_base)[1] = req->opcode; } @@ -134,7 +142,10 @@ unsigned int XCBSendRequest(XCBConnection *c, int flags, struct iovec *vector, c longlen = 0; } else if(longlen > XCBGetMaximumRequestLength(c)) + { + _xcb_conn_shutdown(c); return 0; /* server can't take this; maybe need BIGREQUESTS? */ + } /* set the length field. */ ((CARD16 *) vector[0].iov_base)[1] = shortlen; @@ -144,8 +155,10 @@ unsigned int XCBSendRequest(XCBConnection *c, int flags, struct iovec *vector, c flags &= ~XCB_REQUEST_RAW; /* do we need to work around the X server bug described in glx.xml? */ - if(req->ext && !req->isvoid && strcmp(req->ext->name, "GLX") && - ((req->opcode == 17 && ((CARD32 *) vector[0].iov_base)[0] == 0x10004) || + /* XXX: GetFBConfigs won't use BIG-REQUESTS in any sane + * configuration, but that should be handled here anyway. */ + if(req->ext && !req->isvoid && !strcmp(req->ext->name, "GLX") && + ((req->opcode == 17 && ((CARD32 *) vector[0].iov_base)[1] == 0x10004) || req->opcode == 21)) workaround = WORKAROUND_GLX_GET_FB_CONFIGS_BUG; @@ -155,17 +168,24 @@ unsigned int XCBSendRequest(XCBConnection *c, int flags, struct iovec *vector, c while(c->out.writing) pthread_cond_wait(&c->out.cond, &c->iolock); - if(req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2) + request = ++c->out.request; + /* send GetInputFocus (sync) when 64k-2 requests have been sent without + * a reply. + * Also send sync (could use NoOp) at 32-bit wrap to avoid having + * applications see sequence 0 as that is used to indicate + * an error in sending the request */ + while((req->isvoid && + c->out.request == c->in.request_expected + (1 << 16) - 1) || + request == 0) { prefix[0] = sync.packet; - request = ++c->out.request; _xcb_in_expect_reply(c, request, WORKAROUND_NONE, XCB_REQUEST_DISCARD_REPLY); c->in.request_expected = c->out.request; + request = ++c->out.request; } - request = ++c->out.request; - assert(request != 0); - _xcb_in_expect_reply(c, request, workaround, flags); + if(workaround != WORKAROUND_NONE || flags != 0) + _xcb_in_expect_reply(c, request, workaround, flags); if(!req->isvoid) c->in.request_expected = c->out.request; @@ -183,7 +203,10 @@ unsigned int XCBSendRequest(XCBConnection *c, int flags, struct iovec *vector, c } if(!write_block(c, vector, veclen)) + { + _xcb_conn_shutdown(c); request = 0; + } pthread_mutex_unlock(&c->iolock); return request; } @@ -191,6 +214,8 @@ unsigned int XCBSendRequest(XCBConnection *c, int flags, struct iovec *vector, c int XCBFlush(XCBConnection *c) { int ret; + if(c->has_error) + return 0; pthread_mutex_lock(&c->iolock); ret = _xcb_out_flush_to(c, c->out.request); pthread_mutex_unlock(&c->iolock); @@ -235,8 +260,8 @@ int _xcb_out_send(XCBConnection *c, struct iovec **vector, int *count) int _xcb_out_flush_to(XCBConnection *c, unsigned int request) { - assert(request <= c->out.request); - if(c->out.request_written >= request) + assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request)); + if(XCB_SEQUENCE_COMPARE(c->out.request_written, >=, request)) return 1; if(c->out.queue_len) { @@ -249,6 +274,6 @@ int _xcb_out_flush_to(XCBConnection *c, unsigned int request) } while(c->out.writing) pthread_cond_wait(&c->out.cond, &c->iolock); - assert(c->out.request_written >= request); + assert(XCB_SEQUENCE_COMPARE(c->out.request_written, >=, request)); return 1; }