X-Git-Url: http://git.demorecorder.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fxcb_in.c;h=2ac1e5239c728dd5aa44f6748eb67d2cde4e870f;hb=2c8b5994b3fbba343199ef555594a32e29d8bcee;hp=db9d1ca4d428b2503b60aa64ba1a0b229d9a4053;hpb=6f369fde3c676e2b1a67bd71923b61942991d726;p=free-sw%2Fxcb%2Flibxcb diff --git a/src/xcb_in.c b/src/xcb_in.c index db9d1ca..2ac1e52 100644 --- a/src/xcb_in.c +++ b/src/xcb_in.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "xcb.h" @@ -90,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) @@ -107,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; @@ -140,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); @@ -162,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; } @@ -180,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; } @@ -248,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) @@ -301,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); @@ -311,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; @@ -322,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); } @@ -339,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); @@ -346,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))) @@ -367,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; } @@ -442,18 +490,19 @@ void _xcb_in_destroy(_xcb_in *in) int _xcb_in_expect_reply(XCBConnection *c, unsigned int request, enum workarounds workaround, int flags) { - if(workaround != WORKAROUND_NONE || flags != 0) + pending_reply *pend = malloc(sizeof(pending_reply)); + assert(workaround != WORKAROUND_NONE || flags != 0); + if(!pend) { - pending_reply *pend = malloc(sizeof(pending_reply)); - if(!pend) - return 0; - pend->request = request; - pend->workaround = workaround; - pend->flags = flags; - pend->next = 0; - *c->in.pending_replies_tail = pend; - c->in.pending_replies_tail = &pend->next; + _xcb_conn_shutdown(c); + return 0; } + pend->request = request; + pend->workaround = workaround; + pend->flags = flags; + pend->next = 0; + *c->in.pending_replies_tail = pend; + c->in.pending_replies_tail = &pend->next; return 1; } @@ -464,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) @@ -481,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;