[PATCH libX11] XCB: Add more friendly error messages for common asserts
Daniel Stone
daniel at fooishbar.org
Fri May 13 03:03:54 PDT 2011
This patch adds more friendly error messages for three common classes of
assertion:
- missed sequence numbers due to being griefed by another thread
- unknown requests in queue due to being griefed by another thread
- extensions dequeuing too much or too little reply data
It adds error messages offering advice (e.g. call XInitThreads() first)
on stderr, but still generates actual assertions. Hopefully this means
it's a little more Googleable and a little less frightening.
Signed-off-by: Daniel Stone <daniel at fooishbar.org>
---
src/xcb_io.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 89 insertions(+), 16 deletions(-)
diff --git a/src/xcb_io.c b/src/xcb_io.c
index 8930736..4dadc88 100644
--- a/src/xcb_io.c
+++ b/src/xcb_io.c
@@ -15,6 +15,7 @@
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
+#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -22,6 +23,16 @@
#include <sys/select.h>
#endif
+#define throw_thread_fail_assert(_message, _var) { \
+ unsigned int _var = 1; \
+ fprintf(stderr, "[xcb] " _message "\n"); \
+ fprintf(stderr, \
+ "Most likely this is a multi-threaded client and XInitThreads " \
+ "has not been called\n"); \
+ fprintf(stderr, "Aborting, sorry about that.\n"); \
+ assert(!_var); \
+}
+
static void return_socket(void *closure)
{
Display *dpy = closure;
@@ -51,9 +62,14 @@ static void require_socket(Display *dpy)
* happens while Xlib does not own the socket. A
* complete fix would be to make XCB's public API use
* 64-bit sequence numbers. */
- assert(!(sizeof(unsigned long) > sizeof(unsigned int)
- && dpy->xcb->event_owner == XlibOwnsEventQueue
- && (sent - dpy->last_request_read >= (UINT64_C(1) << 32))));
+ if ((sizeof(unsigned long) > sizeof(unsigned int) &&
+ dpy->xcb->event_owner == XlibOwnsEventQueue &&
+ (sent - dpy->last_request_read >= (UINT64_C(1) << 32)))) {
+ throw_thread_fail_assert("Sequence number wrapped beyond "
+ "32 bits while Xlib did not own "
+ "the socket",
+ xcb_xlib_seq_number_wrapped);
+ }
dpy->xcb->last_flushed = dpy->request = sent;
dpy->bufmax = dpy->xcb->real_bufmax;
}
@@ -125,9 +141,19 @@ static PendingRequest *append_pending_request(Display *dpy, unsigned long sequen
node->reply_waiter = 0;
if(dpy->xcb->pending_requests_tail)
{
- assert(XLIB_SEQUENCE_COMPARE(dpy->xcb->pending_requests_tail->sequence, <, node->sequence));
- assert(dpy->xcb->pending_requests_tail->next == NULL);
- dpy->xcb->pending_requests_tail->next = node;
+ if (XLIB_SEQUENCE_COMPARE(dpy->xcb->pending_requests_tail->sequence,
+ >=, node->sequence))
+ {
+ throw_thread_fail_assert("Unknown sequence number while "
+ "appending request",
+ xcb_xlib_seq_number_wrapped);
+ }
+ if (dpy->xcb->pending_requests_tail->next != NULL) {
+ throw_thread_fail_assert("Unknown request in queue while "
+ "appending request",
+ xcb_xlib_seq_number_wrapped);
+ }
+ dpy->xcb->pending_requests_tail->next = node;
}
else
dpy->xcb->pending_requests = node;
@@ -137,15 +163,30 @@ static PendingRequest *append_pending_request(Display *dpy, unsigned long sequen
static void dequeue_pending_request(Display *dpy, PendingRequest *req)
{
- assert(req == dpy->xcb->pending_requests);
+ if (req != dpy->xcb->pending_requests)
+ {
+ throw_thread_fail_assert("Unknown request in queue while "
+ "dequeuing",
+ xcb_xlib_seq_number_wrapped);
+ }
dpy->xcb->pending_requests = req->next;
if(!dpy->xcb->pending_requests)
{
- assert(req == dpy->xcb->pending_requests_tail);
+ if (req != dpy->xcb->pending_requests_tail)
+ {
+ throw_thread_fail_assert("Unknown request in queue while "
+ "dequeuing",
+ xcb_xlib_seq_number_wrapped);
+ }
dpy->xcb->pending_requests_tail = NULL;
}
- else
- assert(XLIB_SEQUENCE_COMPARE(req->sequence, <, dpy->xcb->pending_requests->sequence));
+ else if (XLIB_SEQUENCE_COMPARE(req->sequence, >=,
+ dpy->xcb->pending_requests->sequence))
+ {
+ throw_thread_fail_assert("Unknown sequence number while "
+ "dequeuing request",
+ xcb_xlib_threads_sequence_lost);
+ }
free(req);
}
@@ -218,7 +259,13 @@ static xcb_generic_reply_t *poll_for_event(Display *dpy)
if(!req || XLIB_SEQUENCE_COMPARE(event_sequence, <, req->sequence)
|| (event->response_type != X_Error && event_sequence == req->sequence))
{
- assert(XLIB_SEQUENCE_COMPARE(event_sequence, <=, dpy->request));
+ if (XLIB_SEQUENCE_COMPARE(event_sequence, >,
+ dpy->request))
+ {
+ throw_thread_fail_assert("Unknown sequence number "
+ "while processing queue",
+ xcb_xlib_threads_sequence_lost);
+ }
dpy->last_request_read = event_sequence;
dpy->xcb->next_event = NULL;
return (xcb_generic_reply_t *) event;
@@ -237,7 +284,12 @@ static xcb_generic_reply_t *poll_for_response(Display *dpy)
!req->reply_waiter &&
xcb_poll_for_reply(dpy->xcb->connection, req->sequence, &response, &error))
{
- assert(XLIB_SEQUENCE_COMPARE(req->sequence, <=, dpy->request));
+ if(XLIB_SEQUENCE_COMPARE(req->sequence, >, dpy->request))
+ {
+ throw_thread_fail_assert("Unknown sequence number while "
+ "processing queue",
+ xcb_xlib_threads_sequence_lost);
+ }
dpy->last_request_read = req->sequence;
if(response)
break;
@@ -512,7 +564,15 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
char *reply;
PendingRequest *current;
- assert(!dpy->xcb->reply_data);
+ if (dpy->xcb->reply_data)
+ {
+ fprintf(stderr, "[xcb] Extra reply data still left in queue\n");
+ fprintf(stderr,
+ "Most likely this is caused by a broken X extension "
+ "library\n");
+ fprintf(stderr, "Aborting, sorry about that.\n");
+ assert(!dpy->xcb->reply_data);
+ }
if(dpy->flags & XlibDisplayIOError)
return 0;
@@ -568,7 +628,11 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
req->reply_waiter = 0;
ConditionBroadcast(dpy, dpy->xcb->reply_notify);
- assert(XLIB_SEQUENCE_COMPARE(req->sequence, <=, dpy->request));
+ if(XLIB_SEQUENCE_COMPARE(req->sequence, >, dpy->request)) {
+ throw_thread_fail_assert("Unknown sequence number while "
+ "processing queue",
+ xcb_xlib_threads_sequence_lost);
+ }
dpy->last_request_read = req->sequence;
if(!response)
dequeue_pending_request(dpy, req);
@@ -665,8 +729,17 @@ int _XRead(Display *dpy, char *data, long size)
assert(size >= 0);
if(size == 0)
return 0;
- assert(dpy->xcb->reply_data != NULL);
- assert(dpy->xcb->reply_consumed + size <= dpy->xcb->reply_length);
+ if(dpy->xcb->reply_data == NULL ||
+ dpy->xcb->reply_consumed + size > dpy->xcb->reply_length) {
+ unsigned int xcb_xlib_too_much_data_requested = 1;
+ fprintf(stderr,
+ "[xcb] Too much data requested for reading from _XRead\n");
+ fprintf(stderr,
+ "Most likely this is caused by a broken X extension "
+ "library\n");
+ fprintf(stderr, "Aborting, sorry about that.\n");
+ assert(!xcb_xlib_too_much_data_requested);
+ }
memcpy(data, dpy->xcb->reply_data + dpy->xcb->reply_consumed, size);
dpy->xcb->reply_consumed += size;
_XFreeReplyData(dpy, False);
--
1.7.4.4
More information about the xorg-devel
mailing list