diff --git a/src/xcb_in.c b/src/xcb_in.c index 4998cdd..bd3131e 100644 --- a/src/xcb_in.c +++ b/src/xcb_in.c @@ -46,6 +46,7 @@ #ifdef _WIN32 #include "xcb_windefs.h" #endif /* _WIN32 */ +#include #define XCB_ERROR 0 #define XCB_REPLY 1 @@ -299,17 +300,51 @@ static int read_block(const int fd, void *buf, const ssize_t len) return len; } +void printBacktrace() { + int j, nptrs; +#define SIZE 100 + void *buffer[100]; + char **strings; + + nptrs = backtrace(buffer, SIZE); + printf("backtrace() returned %d addresses\n", nptrs); + + /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO) + would produce similar output to the following: */ + + strings = backtrace_symbols(buffer, nptrs); + if (strings == NULL) { + perror("backtrace_symbols"); + exit(EXIT_FAILURE); + } + + for (j = 0; j < nptrs; j++) + printf("%s\n", strings[j]); + + free(strings); +} + static int poll_for_reply(xcb_connection_t *c, uint64_t request, void **reply, xcb_generic_error_t **error) { struct reply_list *head; +// printf( "poll_for_reply: request=%llu\n", request ); + + if (request > 1099511627776 ) { // 2^40 + printf( "poll_for_reply: request=%llu\n", request ); + printBacktrace(); + } /* If an error occurred when issuing the request, fail immediately. */ - if(!request) + if(!request) { head = 0; + printf( "poll_for_reply: head=0\n" ); + } /* 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(XCB_SEQUENCE_COMPARE(request, <, c->in.request_read)) { + printf( "poll_for_reply: request < c->in.request_read: %llu < %llu\n", request, c->in.request_read ); + head = _xcb_map_remove(c->in.replies, request); if(head && head->next) _xcb_map_put(c->in.replies, request, head->next); @@ -318,6 +353,8 @@ static int poll_for_reply(xcb_connection_t *c, uint64_t request, void **reply, x * have a reply ready to return. So just return it without blocking. */ else if(request == c->in.request_read && c->in.current_reply) { + printf( "poll_for_reply: request == c->in.request_read && c->in.current_reply: %llu == %llu && %d\n", request, c->in.request_read, c->in.current_reply == NULL); + head = c->in.current_reply; c->in.current_reply = head->next; if(!head->next) @@ -325,12 +362,16 @@ static int poll_for_reply(xcb_connection_t *c, uint64_t request, void **reply, x } /* We know this request can't have any more replies, and we've already * established it doesn't have a reply now. Don't bother blocking. */ - else if(request == c->in.request_completed) + else if(request == c->in.request_completed) { + printf( "poll_for_reply: request == c->in.request_completed: %llu == %llu\n", request, c->in.request_completed ); head = 0; + } /* We may have more replies on the way for this request: block until we're * sure. */ - else + else { + // printf( "poll_for_reply: else\n" ); return 0; + } if(error) *error = 0; @@ -340,6 +381,8 @@ static int poll_for_reply(xcb_connection_t *c, uint64_t request, void **reply, x { if(((xcb_generic_reply_t *) head->reply)->response_type == XCB_ERROR) { + printf( "poll_for_reply: xcb_error\n" ); + if(error) *error = head->reply; else @@ -351,11 +394,15 @@ static int poll_for_reply(xcb_connection_t *c, uint64_t request, void **reply, x free(head); } + printf( "poll_for_reply: return 1\n" ); + return 1; } static void insert_reader(reader_list **prev_reader, reader_list *reader, uint64_t request, pthread_cond_t *cond) { + printf( "insert_reader: request=%llu\n", request ); + while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, request)) prev_reader = &(*prev_reader)->next; reader->request = request; @@ -366,6 +413,8 @@ static void insert_reader(reader_list **prev_reader, reader_list *reader, uint64 static void remove_reader(reader_list **prev_reader, reader_list *reader) { + printf( "remove_reader: reader->request=%llu\n", reader->request ); + while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, reader->request)) if(*prev_reader == reader) { @@ -377,6 +426,7 @@ static void remove_reader(reader_list **prev_reader, reader_list *reader) static void *wait_for_reply(xcb_connection_t *c, uint64_t request, xcb_generic_error_t **e) { void *ret = 0; + printf( "wait_for_reply: request=%llu\n", request ); /* If this request has not been written yet, write it. */ if(c->out.return_socket || _xcb_out_flush_to(c, request)) @@ -416,9 +466,20 @@ void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_ if(c->has_error) return 0; + printf( "xcb_wait_for_reply: request=%u, c->out.request=%llu widen_request=%llu\n", request, c->out.request, widen(c, request) ); + pthread_mutex_lock(&c->iolock); ret = wait_for_reply(c, widen(c, request), e); pthread_mutex_unlock(&c->iolock); + + if ( ret != NULL ) { + printf( "xcb_wait_for_reply: ret.response_type=%d, ret.sequence=%d\n", + ((xcb_generic_reply_t*)ret)->response_type, + ((xcb_generic_reply_t*)ret)->sequence); + } else { + printf( "xcb_wait_for_reply: ret=NULL\n" ); + } + return ret; } @@ -500,6 +561,7 @@ int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply, return 1; /* would not block */ } assert(reply != 0); + //printf( "xcb_poll_for_reply: request=%u, c->out.request=%llu widen_request=%llu\n", request, c->out.request, widen(c, request) ); pthread_mutex_lock(&c->iolock); ret = poll_for_reply(c, widen(c, request), reply, error); pthread_mutex_unlock(&c->iolock); @@ -615,6 +677,7 @@ void _xcb_in_destroy(_xcb_in *in) void _xcb_in_wake_up_next_reader(xcb_connection_t *c) { int pthreadret; + if(c->in.readers) pthreadret = pthread_cond_signal(c->in.readers->data); else diff --git a/src/xcb_out.c b/src/xcb_out.c index c0601f2..d423e49 100644 --- a/src/xcb_out.c +++ b/src/xcb_out.c @@ -30,6 +30,9 @@ #include #include +#include +#include + #include "xcb.h" #include "xcbext.h" #include "xcbint.h" @@ -283,13 +286,44 @@ int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), v return ret; } +void printBacktrace2() { + int j, nptrs; +#define SIZE 100 + void *buffer[100]; + char **strings; + + nptrs = backtrace(buffer, SIZE); + printf("backtrace() returned %d addresses\n", nptrs); + + /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO) + * would produce similar output to the following: */ + + strings = backtrace_symbols(buffer, nptrs); + if (strings == NULL) { + perror("backtrace_symbols"); + exit(EXIT_FAILURE); + } + + for (j = 0; j < nptrs; j++) + printf("%s\n", strings[j]); + + free(strings); +} + + int xcb_writev(xcb_connection_t *c, struct iovec *vector, int count, uint64_t requests) { int ret; + uint64_t tmp = c->out.request; + if(c->has_error) return 0; pthread_mutex_lock(&c->iolock); c->out.request += requests; + if (c->out.request < tmp) { + printf("xcb_writev: requests=%llu, c->out.request=%llu, old out.request=%llu\n", requests, c->out.request, tmp); + printBacktrace(); + } ret = _xcb_out_send(c, vector, count); pthread_mutex_unlock(&c->iolock); return ret;