From 02ba27f37ffde181536f4f76097c3b95ead88680 Mon Sep 17 00:00:00 2001 From: Jamey Sharp Date: Fri, 18 Mar 2011 22:00:10 -0700 Subject: [PATCH] Wake up _XReadEvents when _XReply might need a turn. This fixes the remaining known multi-thread "gotcha" left over after commit 933aee1d5c53b0cc7d608011a29188b594c8d70b. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=30450 Signed-off-by: Jamey Sharp Reviewed-by: Josh Triplett --- src/xcb_io.c | 27 +++++++++++++++++---------- 1 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/xcb_io.c b/src/xcb_io.c index 8930736..ed66cd9 100644 --- a/src/xcb_io.c +++ b/src/xcb_io.c @@ -337,9 +337,20 @@ void _XReadEvents(Display *dpy) if(!dpy->xcb->next_event) { xcb_generic_event_t *event; + unsigned long next_reply; + if(dpy->xcb->pending_requests) + next_reply = dpy->xcb->pending_requests->sequence; + else + { + /* Make sure the Display's sequence + * numbers are valid. */ + require_socket(dpy); + next_reply = dpy->request; + } + dpy->xcb->event_waiter = 1; UnlockDisplay(dpy); - event = xcb_wait_for_event(dpy->xcb->connection); + event = xcb_wait_for_event_until(dpy->xcb->connection, next_reply); /* It appears that classic Xlib respected user * locks when waking up after waiting for * events. However, if this thread did not have @@ -351,8 +362,6 @@ void _XReadEvents(Display *dpy) InternalLockDisplay(dpy, /* ignore user locks */ 1); dpy->xcb->event_waiter = 0; ConditionBroadcast(dpy, dpy->xcb->event_notify); - if(!event) - _XIOError(dpy); dpy->xcb->next_event = event; } @@ -365,11 +374,11 @@ void _XReadEvents(Display *dpy) response = poll_for_response(dpy); if(response) handle_response(dpy, response, False); - else if(dpy->xcb->pending_requests->reply_waiter) + else if(dpy->xcb->pending_requests && dpy->xcb->pending_requests->reply_waiter) { /* need braces around ConditionWait */ ConditionWait(dpy, dpy->xcb->reply_notify); } - else + else if(xcb_connection_has_error(dpy->xcb->connection)) _XIOError(dpy); } @@ -553,11 +562,9 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard) { xcb_generic_reply_t *event; /* If some thread is already waiting for events, - * it will get the first one. That thread must - * process that event before we can continue. */ - /* FIXME: That event might be after this reply, - * and might never even come--or there might be - * multiple threads trying to get events. */ + * it will get the first one, if there are any + * before this reply. That thread must process + * that event before we can continue. */ while(dpy->xcb->event_waiter) { /* need braces around ConditionWait */ ConditionWait(dpy, dpy->xcb->event_notify); -- 1.7.2.3