X-Git-Url: http://git.demorecorder.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fxcb_in.c;h=2ac1e5239c728dd5aa44f6748eb67d2cde4e870f;hb=2c8b5994b3fbba343199ef555594a32e29d8bcee;hp=3bf54f3b8f27c40a0a38a2335b5902ebd94e7a5a;hpb=771761ccaad31d029d470dde84279e94494310b6;p=free-sw%2Fxcb%2Flibxcb diff --git a/src/xcb_in.c b/src/xcb_in.c index 3bf54f3..2ac1e52 100644 --- a/src/xcb_in.c +++ b/src/xcb_in.c @@ -91,11 +91,11 @@ static int read_packet(XCBConnection *c) /* Compute 32-bit sequence number of this packet. */ if((genrep.response_type & 0x7f) != XCBKeymapNotify) { - int lastread = c->in.request_read; + unsigned int lastread = c->in.request_read; c->in.request_read = (lastread & 0xffff0000) | genrep.sequence; - if(c->in.request_read < lastread) + if(XCB_SEQUENCE_COMPARE(c->in.request_read, <, lastread)) c->in.request_read += 0x10000; - if(c->in.request_read > c->in.request_expected) + if(XCB_SEQUENCE_COMPARE(c->in.request_read, >, c->in.request_expected)) c->in.request_expected = c->in.request_read; if(c->in.request_read != lastread) @@ -108,10 +108,11 @@ static int read_packet(XCBConnection *c) } c->in.request_completed = c->in.request_read - 1; } - if(genrep.response_type != XCBReply) /* error or event */ - c->in.request_completed = c->in.request_read; /* XXX: does event/error imply no more replies? */ + if(genrep.response_type == XCBError) + c->in.request_completed = c->in.request_read; - while(c->in.pending_replies && c->in.pending_replies->request <= c->in.request_completed) + while(c->in.pending_replies && + XCB_SEQUENCE_COMPARE (c->in.pending_replies->request, <=, c->in.request_completed)) { pending_reply *oldpend = c->in.pending_replies; c->in.pending_replies = oldpend->next; @@ -141,7 +142,10 @@ static int read_packet(XCBConnection *c) buf = malloc(length + (genrep.response_type == XCBReply ? 0 : sizeof(CARD32))); if(!buf) + { + _xcb_conn_shutdown(c); return 0; + } if(_xcb_in_read_block(c, buf, length) <= 0) { free(buf); @@ -163,17 +167,25 @@ static int read_packet(XCBConnection *c) reader_list *reader; struct reply_list *cur = malloc(sizeof(struct reply_list)); if(!cur) + { + _xcb_conn_shutdown(c); return 0; + } cur->reply = buf; cur->next = 0; *c->in.current_reply_tail = cur; c->in.current_reply_tail = &cur->next; - for(reader = c->in.readers; reader && reader->request <= c->in.request_read; reader = reader->next) + for(reader = c->in.readers; + reader && + XCB_SEQUENCE_COMPARE(reader->request, <=, c->in.request_read); + reader = reader->next) + { if(reader->request == c->in.request_read) { pthread_cond_signal(reader->data); break; } + } return 1; } @@ -181,6 +193,7 @@ static int read_packet(XCBConnection *c) event = malloc(sizeof(struct event_list)); if(!event) { + _xcb_conn_shutdown(c); free(buf); return 0; } @@ -249,7 +262,7 @@ static int poll_for_reply(XCBConnection *c, unsigned int request, void **reply, head = 0; /* We've read requests past the one we want, so if it has replies we have * them all and they're in the replies map. */ - else if(request < c->in.request_read) + else if(XCB_SEQUENCE_COMPARE(request, <, c->in.request_read)) { head = _xcb_map_remove(c->in.replies, request); if(head && head->next) @@ -302,6 +315,8 @@ void *XCBWaitForReply(XCBConnection *c, unsigned int request, XCBGenericError ** void *ret = 0; if(e) *e = 0; + if(c->has_error) + return 0; pthread_mutex_lock(&c->iolock); @@ -312,8 +327,13 @@ void *XCBWaitForReply(XCBConnection *c, unsigned int request, XCBGenericError ** reader_list reader; reader_list **prev_reader; - for(prev_reader = &c->in.readers; *prev_reader && (*prev_reader)->request <= request; prev_reader = &(*prev_reader)->next) + for(prev_reader = &c->in.readers; + *prev_reader && + XCB_SEQUENCE_COMPARE ((*prev_reader)->request, <=, request); + prev_reader = &(*prev_reader)->next) + { /* empty */; + } reader.request = request; reader.data = &cond; reader.next = *prev_reader; @@ -323,12 +343,17 @@ void *XCBWaitForReply(XCBConnection *c, unsigned int request, XCBGenericError ** if(!_xcb_conn_wait(c, &cond, 0, 0)) break; - for(prev_reader = &c->in.readers; *prev_reader && (*prev_reader)->request <= request; prev_reader = &(*prev_reader)->next) + for(prev_reader = &c->in.readers; + *prev_reader && + XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, request); + prev_reader = &(*prev_reader)->next) + { if(*prev_reader == &reader) { *prev_reader = (*prev_reader)->next; break; } + } pthread_cond_destroy(&cond); } @@ -340,6 +365,13 @@ void *XCBWaitForReply(XCBConnection *c, unsigned int request, XCBGenericError ** int XCBPollForReply(XCBConnection *c, unsigned int request, void **reply, XCBGenericError **error) { int ret; + if(c->has_error) + { + *reply = 0; + if(error) + *error = 0; + return 1; /* would not block */ + } assert(reply != 0); pthread_mutex_lock(&c->iolock); ret = poll_for_reply(c, request, reply, error); @@ -347,14 +379,11 @@ int XCBPollForReply(XCBConnection *c, unsigned int request, void **reply, XCBGen return ret; } -XCBGenericEvent *XCBWaitEvent(XCBConnection *c) -{ - return XCBWaitForEvent(c); -} - XCBGenericEvent *XCBWaitForEvent(XCBConnection *c) { XCBGenericEvent *ret; + if(c->has_error) + return 0; pthread_mutex_lock(&c->iolock); /* get_event returns 0 on empty list. */ while(!(ret = get_event(c))) @@ -368,32 +397,50 @@ XCBGenericEvent *XCBWaitForEvent(XCBConnection *c) XCBGenericEvent *XCBPollForEvent(XCBConnection *c, int *error) { - XCBGenericEvent *ret = 0; - pthread_mutex_lock(&c->iolock); + if(!c->has_error) + { + XCBGenericEvent *ret = 0; + int success; + pthread_mutex_lock(&c->iolock); + /* FIXME: follow X meets Z architecture changes. */ + success = _xcb_in_read(c); + if(success) + ret = get_event(c); + pthread_mutex_unlock(&c->iolock); + if(success) + { + if(error) + *error = 0; + return ret; + } + } if(error) - *error = 0; - /* FIXME: follow X meets Z architecture changes. */ - if(_xcb_in_read(c)) - ret = get_event(c); - else if(error) *error = -1; else { fprintf(stderr, "XCBPollForEvent: I/O error occured, but no handler provided.\n"); abort(); } - pthread_mutex_unlock(&c->iolock); - return ret; + return 0; } -unsigned int XCBGetRequestRead(XCBConnection *c) +XCBGenericError *XCBRequestCheck(XCBConnection *c, XCBVoidCookie cookie) { - unsigned int ret; - pthread_mutex_lock(&c->iolock); - /* FIXME: follow X meets Z architecture changes. */ - _xcb_in_read(c); - ret = c->in.request_read; - pthread_mutex_unlock(&c->iolock); + /* FIXME: this could hold the lock to avoid syncing unnecessarily, but + * that would require factoring the locking out of XCBGetInputFocus, + * XCBGetInputFocusReply, and XCBWaitForReply. */ + XCBGenericError *ret; + void *reply; + if(c->has_error) + return 0; + if(XCB_SEQUENCE_COMPARE(cookie.sequence,>,c->in.request_expected) + && XCB_SEQUENCE_COMPARE(cookie.sequence,>,c->in.request_completed)) + { + free(XCBGetInputFocusReply(c, XCBGetInputFocus(c), &ret)); + assert(!ret); + } + reply = XCBWaitForReply(c, cookie.sequence, &ret); + assert(!reply); return ret; } @@ -446,7 +493,10 @@ int _xcb_in_expect_reply(XCBConnection *c, unsigned int request, enum workaround pending_reply *pend = malloc(sizeof(pending_reply)); assert(workaround != WORKAROUND_NONE || flags != 0); if(!pend) + { + _xcb_conn_shutdown(c); return 0; + } pend->request = request; pend->workaround = workaround; pend->flags = flags; @@ -463,7 +513,10 @@ int _xcb_in_read(XCBConnection *c) c->in.queue_len += n; while(read_packet(c)) /* empty */; - return (n > 0) || (n < 0 && errno == EAGAIN); + if((n > 0) || (n < 0 && errno == EAGAIN)) + return 1; + _xcb_conn_shutdown(c); + return 0; } int _xcb_in_read_block(XCBConnection *c, void *buf, int len) @@ -480,7 +533,10 @@ int _xcb_in_read_block(XCBConnection *c, void *buf, int len) { int ret = read_block(c->fd, (char *) buf + done, len - done); if(ret <= 0) + { + _xcb_conn_shutdown(c); return ret; + } } return len;